You always want to use a minimum of CPU per game cycle, right? Looping through all entites, for all entities is therefore not an option and should be done differently. I can do that, most of the time. Please consider this situation:

You have a 2D landscape, in a tower-defence something (RotT for instance) where towers shoot at nearby enemies. How does each tower know, what enemy to target? I actually tried to look in the source code in RotT to find out what the solution used there, and it seems like they're doing what I'd do (roughly):Loop through all targetAble enemies (quickly returning an ArrayList<Type> of the type that is targetAble - data models is not my concern), and get the distance to them, using... hypotenuse of a triangle. Then just keeping in mind which one was the closest one, and bam - we have our answer. But, Math can be expensive - if we have enough towers and enough enemies, we're going to run out of CPU sometime, if we want to loop through things like that.

What can I do to optimize performance, in these situations? I know I can get a copy of Riven's (awesome) fastMath, and I should also ONLY loop through enemies that actually COULD be targeted if they're close enough. Anything else? Practises? Any collections better than others? Smart ways of sorting collections?

That is recommended everywhere, but in my opinion a horrible solution. It complicates things and often results into sub-par performance.

What I did in a 2D fluid-simulator was to create an evenly spaced grid that contained the whole world. You'd fill every cell with the entities that are in that cell. If you're interested which entity can attack which enntity, you just have to check which cells are reachable (loop through rectangles of cells from the source) and iterate over the enitities contained in those cells.

I had even an algorithm that continuously changed the cell-dimensions, searching for the sweet spot.

Hi, appreciate more people! Σ ♥ = ¾Learn how to award medals... and work your way up the social rankings!

I second the grid approach. You can manage the cells you put your entities in very fast by just dividing the position coordinates by the cell size - when using power of two cells you can even optimize this with bit shifts.

Quad trees are only usefull if you have a *vast* amount of irregular placed entities and a *very* big world. It probably only makes sense nowerdays if you have to save memory, too.

The grid cell thing is what I use in Revenge because I'm 99% of the time doing checks for collisions between small objects that are at most 2-3 grid cells in width or height versus other objects of that sort of size. It's highly efficient. I used to use a quadtree but it's much slower.

It would indeed be faster to grab a square chunk out of the world around a turret and then only loop through the entities in that square chunk. Even using grid cells the implementation is pretty fast provided you're not asking for too big a square chunk. In which case you'd be better off with a quadtree, or more likely, simply iterating through every single entity, as let's face it, a distance calc is cheap as chips, being two mults and an add (no need for sqrt if you just need to find who's closest).

How big would said sqaures be? So, each cycle, I'm checking all entities, if they collide with all the rectangles, until a match if found?That sounds intensive, is that really how it should be done? Can I assign entities to tiles easier than that?

I made lot of micro benchmarks and noticed that if/if/if style is really slow, over double time slower when radius is about 10% of map size.Also I noticed that for (Unit unit : unitList) is deadly slow. That kind of loop iterating cost lot more than all inside of it. It made method over three time slower than raw get index loop.

Most of the array will be null objects anyway. Well if you use arrays... I never use ArrayLists because I have better control with just arrays and seems faster aswell, no overhead.Not even 1ms. Five THOUSAND objects.I think its fast enough.

I think you missed the case of the inner loop: which entities can see which entities.

In that case your brute-force loop just got 5000x slower: 4525ms

yea well, in case you really have to check every entity with every entity.I would make towers a separate array or something.well for a RTS its not ideal, but 5000 objects seems high obviously.And also, thats with 5000 objects which are not null. iterating over nulled objects is fast. First line of the loop is -> if != null

In starcraft 1 each could have (without taking over another race) build like what 200 units max.

But I agree, if you really have a lot of objects hanging around, and many of them need to check each other, then you have to do more low level performance thinking

Well... I think, entity-wise, Starcraft and Revenge of the Titans are roughly similar - and I had to pull a few "tricks" like this to get Revenge running at 60fps. Even on my beast of an i7 in survival mode (which is when I first discovered the performance limitations of quadtrees)

Riiight. So let's say your extremely simplified code can be used as a baseline... (it can't be, but let's just assume it is)

If you scale it back to 200 units, it takes 7.24ms per frame. At 60Hz that'd be 434ms per second.

So to wrap up, even with only 200 units, you'd be wasting enormous amounts of CPU cycles. When you'd have 2 players with each 200 units, you'll spend 868ms per second purely on basic visibility checking, while it could easily be 5ms instead.

Hi, appreciate more people! Σ ♥ = ¾Learn how to award medals... and work your way up the social rankings!

My point was to Cero. Its same if you loop units and check if they "collide" with towers or loop towers and check if they "collide" with units. Same amount of method calls. Grid aproach is really nice but I would want see the benchmark where there is 200units with bruteforce vs grid aproach. Grid algorithm scale much better but what is break even point?

It all depends on just how crappy a machine you want it to run on and what else you need to accomplish inside a frame. But still, it's fun doing things the fastest way if you can Revenge ended up having upwards of 1000 entities in it which is half a million collision checks with brute force, definitely way too slow, versus maybe only about 200 or 300 (yes, literally) when using grid cells. In other words I turned the absolute bottleneck which dragged my game down to 10fps into something that was so fast I couldn't even measure it any more.

It all depends on just how crappy a machine you want it to run on and what else you need to accomplish inside a frame. But still, it's fun doing things the fastest way if you can Revenge ended up having upwards of 1000 entities in it which is half a million collision checks with brute force, definitely way too slow, versus maybe only about 200 or 300 (yes, literally) when using grid cells. In other words I turned the absolute bottleneck which dragged my game down to 10fps into something that was so fast I couldn't even measure it any more.

Cas

<edit>Out by a factor of 10

At our not yet published tower defence game units don't collide with each others so there is no problem. Map size is upper limit for towers anyway so there is only 300towers and maybe 500units max. So 150 000 collision check maximum. This is still so deadly fast and use only 15micro seconds with my benchmark. Still might need to do it with grid algorithm when we are doing android version.

There's not just towers but also projectiles to worry about too don't forget. But yes, 150,000 collision checks isn't really a lot, unless you really need those cycles for something else. Anything under a couple of milliseconds is going to leave you plenty of CPU to do graphics and other game logic. Or of course you can cheat at run at 30fps

In my experience it is much faster to clear the grid cells and fill them again, as the remove(..) method is extremely slow compared to a lot of add(...) calls.

I silently assumed that this is dependent on cell transitions per frame, but thinking about it now, it seems unlikely that my approach is faster in a real world scenario. Maybe it could be made faster in certain cases when using a list implementation specially designed for fast add/removal with the help of storing the entities' index in the entity itself (for faster lookup on removal), but it probably might not be worth it...

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