Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (497)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Entity Manager (Searchable)  (Read 2967 times)
0 Members and 1 Guest are viewing this topic.
Offline zngga
« Posted 2012-05-18 02:16:33 »

So I set out to make an entity manager that would allow individual entities search for other entities and get limited amounts of entities for processing, like collision detection. Well here is what I came up with:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
package mbs.exodus.managers;

import java.util.ArrayList;

import mbs.exodus.game.entities.Entity;

public class EntityManager
{
   public static ArrayList<Entity> entities = new ArrayList<Entity>();
   
   public static void registerEntity(Entity e)
   {
      if(e != null)
      {
         entities.add(e);
      }
   }
   
   public static void removeEntity(Entity e)
   {
      if(e != null)
      {
         e.destroy();
         entities.remove(e);
      }
   }
   
   public static Entity[] getEntitiesByOwner(String ownerID)
   {
      Entity[] e = new Entity[entities.size()];
      entities.toArray(e);
      return getEntitiesByOwner(ownerID,e);
   }
   
   public static Entity[] getEntitiesByOwner(String ownerID, Entity[] sample)
   {
      ArrayList<Entity> list = new ArrayList<Entity>();
      for(Entity e : sample)
      {
         if(e.getOwnerID().equals(ownerID))
         {
            list.add(e);
         }
      }
      Entity[] entityArray = new Entity[list.size()];
      list.toArray(entityArray);
      return entityArray;
   }
   
   public static Entity[] getEntitiesByLocation(int x, int y, int radius)
   {
      Entity[] e = new Entity[entities.size()];
      entities.toArray(e);
      return getEntitiesByLocation(x,y,radius,e);
   }
   
   public static Entity[] getEntitiesByLocation(int x, int y, int radius, Entity[] sample)
   {
      ArrayList<Entity> list = new ArrayList<Entity>();
      for(Entity e : sample)
      {
         if(Math.abs(Math.sqrt((Math.pow((x - (e.getX() + e.getSizeX()/2)), 2)) +
               (Math.pow((y - (e.getY() + e.getSizeY()/2)), 2)))) < radius)
         {
            list.add(e);
         }
      }
      Entity[] entityArray = new Entity[list.size()];
      list.toArray(entityArray);
      return entityArray;
   }
   
   public static Entity getEntityByClick(int x, int y)
   {
      Entity entity = null;
      for(Entity e : entities)
      {
         if(x < (e.getX() + e.getSizeX()) && x > e.getX() && y < (e.getY() + e.getSizeY()) && y > e.getY())
         {
            entity = e;
            break;
         }
      }
      return entity;
   }
}


So an individual entity can ask the manager for only the entities within firing range for example (no need to do operations on things out of range)
or you can ask for only the entities within visible range, so you only render entities visible on the screen
lot of things you can do...

My only concern is when there are thousands of entities registered with the manager... if asking for limited entity sets every update is actually slower than doing operations and decision logic on all the thousands of entities every update instead. I will only know when I have thousands of entities! haha!

Anyway I thought I would share, and hopefully get some pointers, and maybe inspire someone to climb one step higher in the quest for the perfect entity manager!

My code never has bugs... it just develops unexpected features!
Offline actual

JGO Coder


Medals: 23



« Reply #1 - Posted 2012-05-18 04:26:28 »

If you are worried about performance, a small think you can do is to change the if comparison in getEntitiesByLocation to:

1  
2  
3  
4  
5  
6  
float x1= x - e.getX() + e.getSizeX()/2;
float y1= y - e.getY() + e.getSizeY()/2;

if (x1*x1 + y1*y1 < radius*radius) {
  list.add(e);
}


You get rid of the relatively expensive square root operation and replace two Math.pow operations for faster multiplication calls. It's a micro optimization but could make a difference when dealing with large numbers of entities. Also is there a reason you flip between lists and arrays? Given that you are already storing the entities as lists, why not have the functions return lists of entities rather than converting them to arrays?

Offline 65K
« Reply #2 - Posted 2012-05-18 06:07:46 »

For dealing with thousands of entities in a frequently called game loop, I wouldn't create array copies each and every time. Theoretically its good for protecting the private members (if entities was private here...).
Instead, a visitor callback would be an alternative.
If you want to return copies, lists are more flexible and abstract than arrays.
Then, using enhanced loops creates lots of avoidable iterators in the background.
If you absolutely need static access, instead of making each method static, rather deal with a static entity manager in a whole.

So far for my suggestions  Smiley

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Roquen
« Reply #3 - Posted 2012-05-18 08:20:35 »

Using purely algebraic reductions that you're familiar with is a good habit to get into.  Calling Math.pow with an integer (esp small) exponent should be avoided (bad habit)...it's much much slower and less accurate (plus it's more typing).  Not that the accuracy is likely to be important.
Offline matheus23

JGO Kernel


Medals: 107
Projects: 3


You think about my Avatar right now!


« Reply #4 - Posted 2012-05-18 11:35:22 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
public static Entity getEntityByClick(int x, int y)
   {
      Entity entity = null;
      for(Entity e : entities)
      {
         if(x < (e.getX() + e.getSizeX()) && x > e.getX() && y < (e.getY() + e.getSizeY()) && y > e.getY())
         {
            entity = e;
            break;
         }
      }
      return entity;
   }


I think that break would only break out of the if-clause. Thats better IMO:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
public static Entity getEntityByClick(int x, int y)
   {
      Entity entity = null;
      for(Entity e : entities)
      {
         if(x < (e.getX() + e.getSizeX()) && x > e.getX() && y < (e.getY() + e.getSizeY()) && y > e.getY())
         {
               return e;
         }
      }
      return null;
   }

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline tom
« Reply #5 - Posted 2012-05-18 12:45:32 »

I think that break would only break out of the if-clause. Thats better IMO:
No, it will break out of the for loop.

Offline matheus23

JGO Kernel


Medals: 107
Projects: 3


You think about my Avatar right now!


« Reply #6 - Posted 2012-05-18 13:48:28 »

I think that break would only break out of the if-clause. Thats better IMO:
No, it will break out of the for loop.

Okey... that version was strange anyways. So if that code would break out the for loop, why do it that way, and not just return ?

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline actual

JGO Coder


Medals: 23



« Reply #7 - Posted 2012-05-18 13:52:58 »

I think that break would only break out of the if-clause. Thats better IMO:
No, it will break out of the for loop.

Okey... that version was strange anyways. So if that code would break out the for loop, why do it that way, and not just return ?

Not sure for the OP's motivation, but some believe that a function or method should only have a single exit point (let's forget exceptions for the moment).  You can Google function single exit point to find links to various discussions. In a method this short I don't think it matters.
Offline matheus23

JGO Kernel


Medals: 107
Projects: 3


You think about my Avatar right now!


« Reply #8 - Posted 2012-05-18 13:55:11 »

I think that break would only break out of the if-clause. Thats better IMO:
No, it will break out of the for loop.

Okey... that version was strange anyways. So if that code would break out the for loop, why do it that way, and not just return ?

Not sure for the OP's motivation, but some believe that a function or method should only have a single exit point (let's forget exceptions for the moment).  You can Google function single exit point to find links to various discussions. In a method this short I don't think it matters.

LOL... Then I did that wrong for sooooo much functions... Cheesy

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline actual

JGO Coder


Medals: 23



« Reply #9 - Posted 2012-05-18 14:03:51 »

LOL... Then I did that wrong for sooooo much functions... Cheesy

Personally, I don't see anything wrong with having multiple exit points. If your methods are relatively succinct (as they should be!) then I don't see any practical or theoretical negative consequence of having multiple return statements.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline sproingie

JGO Kernel


Medals: 202



« Reply #10 - Posted 2012-05-18 15:47:34 »

I'm a big believer in early returns for edge cases right up at the top so you don't have the rest of the code stuffed inside conditionals ending with a diagonal wall of curly braces.  Even scala, which eliminated 'break' and 'continue', has a 'return' statement that can break out early (you don't otherwise need it at the end).

Structured programming is a good guideline for clarity, but it shouldn't get in the way of clarity.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #11 - Posted 2012-05-18 17:46:46 »

The EntityManager looks pretty neat, although it would be cool if its functionality was broken out into multiple areas. For example, collisions usually should be handled altogether, so once per frame you might calculate all collisions and store the results somehow with very quick access later. Your code means that every single entity is going to need to perform a check that could be very redundant, so your code will be extremely expensive in comparison.

But if you don't have that many entities, who cares?

See my work:
OTC Software
Offline Roquen
« Reply #12 - Posted 2012-05-18 19:02:38 »

Eli: That sounds distinctly like knowing in advance something is going to be a performance issue and coding to handle it in advance.

BTW: Spatial partitioning approaches exponentially faster for spatial queries.  A nice simple method is to simply have the entities stored in a uniform grid.  Another simply option is sweep-and-prune.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #13 - Posted 2012-05-18 19:46:18 »

Eli: That sounds distinctly like knowing in advance something is going to be a performance issue and coding to handle it in advance.
Pffffft. Don't bring that argument into another thread. And notice I said "but if you don't have that many entities, who cares?"

Writing collision with arbiters is just as much work and is faster too. So why not bring it up? It's a suggestion only.

See my work:
OTC Software
Offline zngga
« Reply #14 - Posted 2012-05-18 23:05:55 »

Thanks for all the tips! Yeah, to be honest, I have no idea why I was converting to regular arrays! I even create new ArrayLists in each method! Thanks, Actual, for the tip on the math for the getEntitiesByLocation method, small performance boost, Ill take it! As far as the static access is concerned, It is just easier for the rest for the program to have static access. I could make it into a nested static class, but I couldn't be bothered! haha! I plan to add a few more methods to help with collision detection, but I won't work on that until later.

My code never has bugs... it just develops unexpected features!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

BurntPizza (25 views)
2014-09-19 03:14:18

Dwinin (39 views)
2014-09-12 09:08:26

Norakomi (68 views)
2014-09-10 13:57:51

TehJavaDev (93 views)
2014-09-10 06:39:09

Tekkerue (47 views)
2014-09-09 02:24:56

mitcheeb (68 views)
2014-09-08 06:06:29

BurntPizza (51 views)
2014-09-07 01:13:42

Longarmx (38 views)
2014-09-07 01:12:14

Longarmx (44 views)
2014-09-07 01:11:22

Longarmx (40 views)
2014-09-07 01:10:19
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!