Moving a sprite along a vector (line)
Hello all,
I am trying to get a simple image to follow the mouse cursor, to let the player control a ship in a shooting game.
The problem is that I don't want the ship to follow exactly on top of the cursor (like a .moveTo method would do), but rather have it so the ship sort of lags behind the cursor, limiting the maximum speed it can travel.
I know how to get the position of the ship, and the position of the cursor, but I don't know how to get the ship to move along the vector created by the two points.
Please help!
[557 byte] By [
Irona] at [2007-11-27 8:37:58]

# 1
first you need to find the angle between the two points (e.g. p1 = mouse, p2 = sprite). use this method:
protected double calcAngle(Point p1,Point p2) {
return Math.atan2(p2.y-p1.y,p2.x-p1.x)*180.0/Math.PI;
}
Then to move along at that angle, use:
sprite.x+=Math.cos(angle)*velocity;
sprite.y+=Math.sin(angle)*velocity;
where velocity is how fast you want it to move
# 2
I don't know where the sprite class is coming from, but when I tried to implement this with the image that I had, it didn't work. Origionally it just made the ship disappear, but now it gives me a null pointer exception. Granted the null pointer is probably MY code, but I can't get this to work.
I have your method:
public double calcAngle(Point p1,Point p2) {
return Math.atan2(p2.y-p1.y,p2.x-p1.x)*180/Math.PI;
}
and the movement I wrote looks like this:
currentPoint.x+=Math.cos(calcAngle(currentPoint, mousePoint))*.1;
currentPoint.y+=Math.sin(calcAngle(currentPoint, mousePoint))*.1;
shipImage.moveTo(currentPoint.getX(), currentPoint.getY());
Basically because I have no sprite class, I change the variable which tracks the current image location, then move the image to that new point.
Can anyone tell me what I'm doing wrong or suggest another way?
Irona at 2007-7-12 20:35:28 >

# 3
why is your sprite and location not part of a single class object? Revise your program structure. Make a "GameObject" class (for example) that has an x,y coordinate and an image. This way, every object will have a place and a picture. That will help the organization...
Now, for the sprite moving...
the calcAngle method he gave you is correct and your usage of the function seems correct as well.. but that third line of code you gave:
shipImage.moveTo(currentPoint.getX(), currentPoint.getY());
I dont get this? If u could access currentPoint.x then why do you need a function currentPoint.getX()?
////
/// THE PROBLEM
///
The problem is that the calcAngle is returning degrees and NOT radians. take out the "180/Math.PI" and give it a try...
Also! multiplying the sin/cos by 0.1 will make the motion VERY slow, maybe its not moving? NOTE: is currentPoint.x an integer? maybe its truncation the motion? Make sure currentPoint values are doubles.
GOOD LUCK!
# 4
Arik is mostly right
calcAngle should NOT be returning in angles, so that is my fault. however, this would not have been preventing movement, it would simply make it stutter around a bit (but going the right direction)
now, here is why your sprites are not moving..
your sprite's X/Y coordinates are likely stored as ints, but since the velocity is so low, the x-offset (how much the x is going to move) may be something like 0.1432.
so then when you apply that to x, you find the problem:
x+=0.1432
let's say x is 4.
4+=0.1432 = 4.1432
since your x is an int, this is changed to 4. thus, no change! (and no motion)
so you have two options..
1. change velocity to a higher value (though this will not be able to stop pinpoint on the mouse location, since it will eventually be like a 0.02 offset)
2. do all variables with floats or doubles
I suggest option number 2. when it comes to angles, you do need precision.
I have uploaded an example for you to try out:
http://woogley.net/misc/MouseFollow/MouseFollow.jar
just move the mouse around and watch as the ball follows your mouse around. this example is using a velocity of 1.0.
go ahead and play with the source code, change the velocity, etc:
http://woogley.net/misc/MouseFollow/MouseFollow.java
# 5
Thank you VERY MUCH Woogley, it's good to see something that actually does what I was trying to accomplish.
I should be able to figure out how to fix my problem with your code. The problem was most likely that I just haven't been using Java long enough! About a year, I still don't know very much.
Thanks again!
Irona at 2007-7-12 20:35:28 >

# 6
if(cursor.X>image.X) image.X+=moveSpeed;
else if(cursor.X<image.X) image.X-=moveSpeed;
if(cursor.Y>image.Y) image.Y+=moveSpeed;
else if(cursor.Y<image.Y) image.Y-=moveSpeed;
And if you wanted to get more detailed, add in different move speeds for vertical and horizontal...
and scale them in ranges. IE:
this is your loop:
while(true){
checkSpeeds():
updateImage();
}
then these are the methods:
private void checkSpeeds(){
if(Math.abs(image.X-cursor.X)>50) xMoveSpeed=20; //highest tier, tier1
else if(...>40) xMoveSpeed=15; //tier 2
else if(...>30) xMoveSpeed=10; //tier 3
... //ect, do same with yMoveSpeed (referring to velocity)
}
Then just update it or whatever. I'm not sure that's the most efficient way to do it, but off hand that's probably where I'd start.
Sangea at 2007-7-12 20:35:28 >
