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 Attack
s 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 Attack
s 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 Attack
s 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!
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 Point
s to double
s, 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 Attack
s 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.