ForumsProgramming Forum[Intermediate]Calculate Closest Enemy

8 8576
weirdlike
offline
weirdlike
1,299 posts
Prince

For those of you who haven't been following along, take a peek at this demo HERE

var enemyArray:Array = new Array();

function enterFrameLoop(event):void
{
var closestEnemy:Number = 25000000;
for (var i:int = 0; i < enemyArray.length; i++)
{
var currentEnemy:Object = enemyArray[i];
var dist:Number = Math.pow(hero.x-currentEnemy.x,2)+Math.pow(hero.y-currentEnemy.y,2);

if (dist &lt closestEnemy)
{
closestEnemy = dist;

//use currentEnemy for whatever you want
}
}
}

  • 8 Replies
KentyBK
offline
KentyBK
566 posts
Nomad

Considering you don't really need the euclidean distance specifically, why don't you just compare dist² instead? It saves you the potentially expensive square root when you have a ton of enemies.

weirdlike
offline
weirdlike
1,299 posts
Prince

You've peaked my interest. Would you care to elaborate on that?

KentyBK
offline
KentyBK
566 posts
Nomad

Sure, let me try.

See, for your function, you don't necessarily need to calculate the exact distance between objects. All you really need, is a value that's small for close enemies and large for enemies that are far away.

Keeping this in mind, you notice that you don't need to use the sqrt-operation, because Math.pow(hero.x-currentEnemy.x,2)+Math.pow(hero.y-currentEnemy.y,2) alone is still going to be small for close objects and big for far-away objects.

Mind you, if you need to use the exact distance for something else later on, you'd use your example. But just to test which object is closest, the square root is not needed.

weirdlike
offline
weirdlike
1,299 posts
Prince

tested and it does work, one thing to note tho is the max distance to check for will have to be increased in order to keep the same range.

Here are the results:

var original:Number = Math.sqrt(Math.pow(hero.x-currentEnemy.x,2)+Math.pow(hero.y-currentEnemy.y,2));

var new:Number = Math.pow(hero.x-currentEnemy.x,2)+Math.pow(hero.y-currentEnemy.y,2);

180.47636964433872 - original
32571.719999999987 - new

http://i.imgur.com/CPRuQ9v.jpg

Thanks for the tip @KentyBK I will have to do some more testing to see the full effect.

KentyBK
offline
KentyBK
566 posts
Nomad

Then I suggest using 25,000,000 as the max, i.e 5000².

I mean, if you're comparing without the square root, it only makes sense to square the range instead.

weirdlike
offline
weirdlike
1,299 posts
Prince

Well it would appear that I was able to increase the max enemy amount on my game there by about 20 units by eliminating that extra bit.

Edited the original post

mightybob
offline
mightybob
360 posts
Peasant

Hey, this is some neat stuff!

I turned it into a function, here's an example:

nuwbie
offline
nuwbie
11 posts
Nomad

You can make it slightly faster by doing this and save on one iteration: (Although trivial gain)


var currentEnemy:Object = enemyArray[i];

var closestEnemy:Number = Math.pow(hero.x-currentEnemy.x,2)+Math.pow(hero.y-currentEnemy.y,2);

for (var i:int = 1; i < enemyArray.length; i++)
{
currentEnemy:Object = enemyArray[i];
dist:Number = Math.pow(hero.x-currentEnemy.x,2)+Math.pow(hero.y-currentEnemy.y,2);



Although in larger scale applications where you are dealing in the thousands or even millions, you need to index and make grids on the map.

Showing 1-8 of 8