Search code examples
javaeclipsedoublecollision-detectiontrigonometry

Getting double velocity vectors to calculate correctly without rounding


I'm currently writing a simple game where there are a number of towns with a certain number of soldiers that increments every second. Towns owned by one player can attack a town owned by another player, causing the amount of soldiers in the original town to split in half, with the other half going to attack the other town.

The issue is that I represent the attacking soldiers as a shape heading towards the other town, and I use collision detection to figure out when the Attack arrives. Therefore, it's important that the vector the Attack uses to reach the town is correct so that it actually reaches the town.

Every town has a Point field called an attackPoint which I use as the origin point for attacks as well as the destination for them to head to. The attackPoint is located in the middle of the collision field.

Here's the code I have which initializes an Attack and creates the movement vector:

public Attack(int troops, Team owner, Town source, Town destination) {
    this.troops = troops;             //troops included in the attack
    this.owner = owner;               //player that who sent the attack
    this.destination = destination;   //town the attack is going towards

    Point srcPoint = source.getAttackPoint(); //attackPoint of the source
    Point destPoint = destination.getAttackPoint(); //attackPoint of the destination town

    x = srcPoint.x;           //int --- the attack originates at the src's attack point
    y = srcPoint.y;           //int

    double hypotenuse = Math.sqrt(Math.pow(destPoint.y - y, 2) + Math.pow(destPoint.x - x, 2));
    double adjacent = destPoint.x - x;
    double opposite = destPoint.y - y;
    xVelocity = 3.0 * (adjacent / hypotenuse);     //field, double
    yVelocity = 3.0 * (opposite / hypotenuse);
}

Then another method actually moves the Attack -

public void move() {
   x += xVelocity;
   y += yVelocity;
}

I can confirm from testing that the attackPoints returned by getAttackPoint() are both correct, and that the way I do collision detection works fine. The problem here is that it seems either my velocity variables, or some other variables, are getting rounded so that there are only a few predefined paths the Attacks can take. For example:

//trying to attack X2     //trying to attack X1
X...............                     X------------------
.\..............                     .........X1.....
..\.............                     ................
...\............                     ................
....\...........                     ................
.....X1..X2.....                     ................

The "predefined" paths seem to be every 30 degrees or so, and I can send Attacks straight up, down, left, and right, which is why I think some rounding error is going on when I'm calculating the vectors and doing the trig. When I have two towns that are close together, no matter which one I try to attack, both Attacks follow the same path (diagram 1). Also, when I have a town that is close to 180 degrees east/west of the source town, the Attack I send will go directly east/west (diagram 2).

If anyone can see something going wrong or give me a suggestion on how to allow the objects to travel on a direct path from one point or another, that would be much appreciated!


Solution

  • So after researching this more and trying a couple different solutions, I'm pretty convinced that there's some rounding error going on - maybe converting the int fields of the Points to doubles, but I'm not sure.

    What I did to get it to work is to move all the calculation to the move() method so that the line gets recalculated every tick. This is less good for optimization, but I don't have a lot of objects and this helps the Attacks move on a dynamic line towards the other towns. I haven't been able to figure out what was causing the issue initially, but making sure that the calculation was able to check itself by recalculating has solved the problem.