I'm making a server/client game with movement similar to strategy games like Warcraft 1/2/3 etc.. where the player moves by right clicking on somewhere on the area and the character tries to move there. I'm trying to make the character always go in a straight line towards the point until it gets there (or close enough). The code I'm using now gets the character there but in a weird way.
When I click somewhere under the character (higher Y coordinate) it moves in a straight line, but when I click above it (lower Y coordinate), the character moves like it's making a circle while moving, but it still gets there, only not the way I want it to.
Here's the code that runs every update to move it.
if (this.order == "Move")
{
if (Math.Abs(this.orderPos.X - this.warlockPos.X) < this.moveSpeed && Math.Abs(this.orderPos.Y - this.warlockPos.Y) < this.moveSpeed)
{
this.warlockPos = this.orderPos;
this.order = "None";
this.orderPos = Vector2.Zero;
}
else
{
delta = this.orderPos - this.warlockPos;
if (delta.Y == 0)
{
if (delta.X < 0)
angle = -90;
else
angle = 90;
}
else
{
if (delta.Y < 0)
angle = 180 + Math.Atan(delta.X / delta.Y);
else
angle = Math.Atan(delta.X / delta.Y); ;
}
this.warlockPos = new Vector2(this.warlockPos.X + this.moveSpeed * (float)Math.Sin(angle), this.warlockPos.Y + this.moveSpeed * (float)Math.Cos(angle));
}
}
this.order == move means the client's last order was to move. orderPos is the place where the client last told the server the character should move. warlockPos is the current position of the character (where it was by the end of the previous update). moveSpeed is just the speed at which it moves. I use delta and angle to figure out where the character should move in this update.
So, what's making the character move in a circular way when the point it's moving towards is above it?
I see a few problems with this code originating from the use of angles. It's not that you can't use angles, but the code becomes more complicated with this approach and prone to error. Instead, I used some vector methods such as Length()
to check if the warlock is close to his destination, and Normalize()
when I covert the delta vector into a unit vector in the same direction and with the magnitude of his moveSpeed (in order to move him that far). Here is what I came up with:
if (order == "Move")
{
Vector2 delta = orderPos - warlockPos;
if (delta.Length() < moveSpeed)
{
warlockPos = orderPos;
order = "None";
orderPos = Vector2.Zero;
}
else
{
delta.Normalize();
delta *= moveSpeed;
warlockPos += delta;
}
}
I'd also recommend not use the this
keyword if it isn't necessary (only if there is another local variable or parameter with the same name). I apologize if this was an intentional style choice. Also, I'd recommend using an enumeration instead for the order variable (for example order == Orders.Move
).