Alright guys, I have 2 active objects: An Active Unit, and a little circe where he's supposed to be going. I want to be able to click and have the Unit move directly to the Circle at an alterable speed. As it is now, the Unit will move in the general direction of the Circle, but it doesn't go there directly. Also, if someone could explain to me how to put a movement speed cap on the unit, so he doesn't keep accelerating, that would be awesome. Here's how it's working so far:
-User clicks with Left Button
o-(Unit) Set alterable Flag 0 on.
o-(Circle) Set position to Xmouse, YMouse.
o-(Circle) Set val(Stored X) to Xmouse, val(Stored Y) to Ymouse
-(Unit) Flag 0 is on
-(Unit)Xpos < (val(Stored X)of(Circle))+16
-(Unit)Xpos > (val(Stored X)of(Circle))-16
-(Unit)Ypos < (val(Stored Y)of(Circle))+16
-(Unit)Ypos > (val(Stored Y)of(Circle))-16
(I put this line here because for some reason the Unit will move in the general direction of the circle, but won't go straight over it, like I'd like.)
So far, that's all I have and it seems to work alright, but i'd like the Unit to move directly to the Circle. I also noticed that in a lot of the tutorials for Custom Sin/Cos movements, the Sin part is always:
whatever( "Unit" )-((Sin(Movement Angle( "Unit" ))
as opposed to
whatever( "Unit" )+((Sin(Movement Angle( "Unit" ))
but when i make the value negative, it goes in the opposite vertical direction.
What you really want to get is the direction you are headed, and this can be calculated.
Most people will prefer the atan(dy/dx) method, personally I don't like having to deal with the division by 0, so I use
acos(a.b/|a||b|) which is the angle between two vectors. I call the player the origin and I want to know the angle for the direction of this point. We are taking angles as anticlockwise from the x axis, so you start at the point (1, 0) and rotate around anticlockwise. Don't forget that because the y axis is backwards, this actually means the anticlockwise rotation we see is actually a clockwise rotation in terms of the 2d space we are manipulating (and this is very annoying and confusing but we can usually fix problems by fudging around with signs).
So this angle is the angle between the vector (1, 0) and the direction vector (destination x - player x, destination y - player y). We can plug this straight into the equation:
angle = acos(a.b/|a||b|) - where . is the vector dot product and | | is the length of the vector
angle = acos((destination x - player x)/sqrt(((destination x - player x)^2)+(destination y - player y)^2))
So we only get a division by 0 when the player is in the same place as the destination (which we can catch with a simple condition before computing the angle). Unfortunately we can only calculate the angle <= 180 degrees, so we need some way to determine angles > 180 degrees. This can be done by simply checking if the y difference is positive or negative. If the y distance is negative, that is if y player - y destination is negative, the destination is below the player and the angle we require is a reflex angle, or for the angle to go in the opposite direction. Some people might opt to compute 2 angles and take the largest one, but for efficiency I like to calculate 1 angle only.
the y difference dy/dy can be 3 values, -1, 0 or 1. Note we get 0/0 when the y values are identical, but this isn't really a problem and will be computed as 0 and is what we want. really we just want it to be 1 or -1 so to convert it we take ((dy/dy)+0.5) which gives -0.5 0.5 or 1.5, and then we divide by the absolute value to get 1 for the positive numbers and -1 for the negative
((dy/dy)+0.5)/abs((dy/dy)+0.5)
now that dictates the direction, so our angle is ((dy/dy)+0.5)/abs((dy/dy)+0.5)*angle
we could limit this to between 0 and 360, but for what we are going to do with it, this angle is -180 < angle <=180 and will be fine
Now we have the angle, it's easy to move in this angle. I have included an example with all of the acceleration and maximum speed type stuff you will need. If you followed that you're doing pretty well, but I expect quite a few people to be baffled. If you don't get it just take it for granted and use it as is.