Monday 28 November 2011

Distance check

Distance calculations are important in many games. One important example is checking distances to compare them to the range of a weapon or weapons; turrets placed by the player or AI enemies that need to decide when to fire. And because there can be many enemies or turrets in game these calculations may need to be done very often, perhaps many times a frame.


The code I use looks something like this


function CheckForTargets():Enemy {
    var iEnemy:int, enemy:Enemy, fRangeSq:Number, fSep:Number;
    fRangeSq = fRange * fRange;

    for (iEnemy = 0; iEnemy < aEnemies.length; ++iEnemy) {
        enemy = aEnemies[iEnemy];
        fSep = (fX - enemy.fX) * (fX - enemy.fX)
             + (fY - enemy.fY) * (fY - enemy.fY);
        if (fSep < fRangeSq) { // in range
            return enemy;
        }
    return null;
}


There are two important points to this code. First the distance is never calculated. Instead fSep, the square of the distance, is calculated using Pythagoras's theorem. The distance would be Math.sqrt(fSep) but there's no need to calculate this for every target.


Second even though these are DisplayObjects the code does not use their x and y. As noted last week It is faster and more accurate to use the members indicated (fX and fY on all game objects). This is even true if x, y, fX and fY coincide.


aEnemies is a global, sorted list and the code shoots the first in that list (the nearest the exit) that's in range. But it is easy to adapt this to use some other criteria such as the nearest by checking all enemies for the one with the least distance squared, fSep.

No comments:

Post a Comment