Find tile coordinates within a given radius

Started by
9 comments, last by P0jahn 8 years, 7 months ago

Instead of doing a distance check that requires a square root, you can check against the squared distance:


if((j - x)*(j - x) + (k - y)*(k - y) <= r * r)

Should be faster.

Advertisement
I found something very similar. The performance is ok I guess. Took 1.768828 milliseconds when the radius was 20, in Java. Complete code for future reference:

I personally find almost 2 milliseconds is an awful lot. While Java isn't the fastest language in the world, still two milliseconds is an eternity for something so simple.

On the other hand, if you only need to do this once in a while (like, once each time a grenade explodes), it probably makes no difference and it's not worth worrying..

Note the distance-squared optimization that I wrote about and that Mussi pointed out as well.

However, I think that that creating (and then leaking, so the GC has to collect them) all those Vector2 temporaries only for calculating the distance is probably more overhead than doing a square root. Yes, this is how you do Java, but creating and recycling all those objects needlessly is not alltogether free.

Of course, it's also very comfortable, and explicit, to dynamically create those Vector2 objects and call the distance function, and toss the objects away. But calculating a distance (or rather, a squared distance) is so trivial that you could really just do it by hand on the coordinates, without these temporaries. If you have a radius of 20, you allocate and free 1,600 objects to no avail. That doesn't sound like a lot per se, but it's unnecessary and it all adds up (with the stuff in the following paragraph, too).

I would also rather not use a HashSet to store the points that are found to be in the circle, since you are actually only interested in a contiguous list to which you can push your points and which you can iterate over afterwards (so you can draw red squares, or apply damage to units within each cell, etc) in the most efficient manner possible.

This is best represented by a Vector. Other than a HashSet, a Vector does not need to compute a hash (obviously), it does not provide the guarantee that each element exists only once (so, it doesn't need to perform that check for a guarantee that you don't need), doesn't have any other of the underlying implementation's (HashMap) special gimmicks such as null values, and it does not have issues with hash collisions (which, in the current implementation of HashMap that uses chaining means traversing linked lists!).

Added the optimisations suggested here and got it down to 1 ms(radius 20). As samoth mentioned, this is going to be calculated when ever a major bomb explodes, so it is far from every frame. I can live with it.

This topic is closed to new replies.

Advertisement