Vector movement in space type game (Mouse rotation)

I'm having an issue with my movement in my 'game' prototype. It's basically not working and admittedly my knowledge with vectors is lacking.

The issue I'm running into is that the ship won't move in the direction of my mouse. (I'm using my mouse as rotation)

Mouse look example video I took yesterday

I would love it if someone could look at my code/Vector math and tell me if they can notice anything I'm doing terribly wrong, I would greatly appreciate it.

private Vector2f acceleration;
private Vector2f force;
private Vector2f velocity;
private Vector2f position;
private Image image = null;
private float mass;
private float angle;

//Constructors
public Ship(float xin, float yin) {
this.mass = 5000; // temp value of mass
this.angle = 0;

// Image of the ship
try {
this.image = new Image("res/ship.png");
} catch (SlickException e) {
e.printStackTrace();
}

// Vectors
position = new Vector2f(xin, yin);
velocity = new Vector2f(0, 0);
acceleration = new Vector2f(0, 0);
force = new Vector2f(0, 0);
}

public void update(Input input, float delta) {
float mouseX = input.getMouseX();
float mouseY = input.getMouseY();

float xDistance = mouseX - (position.x + image.getWidth()/2);
float yDistance = mouseY - (position.y + image.getHeight()/2);

angle = (float) (Math.toDegrees(Math.atan2(yDistance, xDistance)) + 90);
image.setRotation((float)angle);

if (input.isKeyDown(Input.KEY_W)) {
this.move(delta);
} else if (input.isKeyDown(Input.KEY_S)) {
//this.move(delta);
} else {
acceleration = new Vector2f(0, 0);
}
}

public void move(float delta) {
/*
* Acceleration = Force / Mass
* Velocity += Acceleration * ElapsedTime (delta)
* Position += Velocity * ElapsedTime (delta)
*/
System.out.println(delta); //debugging
//delta = delta/10; //debugging
//System.out.println(delta); //debugging
force = angleToVector(angle); // Direction
force = force.normalise();
force = force.scale(2);
acceleration = force.scale(1/mass);

}

public Vector2f angleToVector(float angle) {
return new Vector2f((float)Math.cos(angle), (float)Math.sin(angle));
}

If you want to see the full .java for my ship class here's a link.

• Did you check with the debugger, what arguments are you passing to move(...), and how they look after the conversion to float? I might be missing somethings, but I don't see where you're setting the 'delta' value. Aug 8, 2012 at 9:12
• @Marton Sorry I left out a pretty important part and just realized, its in the update call. I just updated my code to include that and to remove magnitude. When I first enter the move call delta returns a number between 15.0-18.0. Aug 8, 2012 at 12:18
• I seem to have semi fixed it, it's not working as expected but it is following the mouse and moving towards it. I needed to remove the force.scale(1/mass) line and just replace it with acceleration = force. But it seems as though there's really no physics acting on the ship, I'll try and record a video to give a better idea and I will update the code after that. Aug 8, 2012 at 13:30
• How did you post a video from yesterday and already get over 100 views?! Aug 8, 2012 at 17:10
• @GameDev-er I had a question about a Parallax effect yesterday on Reddit and posted that to show some progress. :) Aug 8, 2012 at 17:37

I notice the following:

When you are updating the angles, you are doing the following:

angle = (float) (Math.toDegrees(Math.atan2(yDistance, xDistance)) + 90);

And when you are moving you are doing this:

force = angleToVector(angle);

Which means you are REALLY doing this:

Vector2f((float)Math.cos(angle), (float)Math.sin(angle))

To break this down:

1. get mouse vector (correct)
2. convert vector to relative vector based on position of ship (correct)
3. convert vectory to radians with Math.atan2 (correct)
6. store in this.angle (correct)

Then, when moving:

1. take the value in this.angle (correct)
2. don't subtract 90 (fail)
3. don't convert to radians (fail)
4. convert to vector with sin and cos (correct)
5. use the force vector to calculate acceleration (correct)
6. use acceleration to move the ship

So, near as I can see, your problem is failing to do two of your conversions the one way that you do the other way.

One potential fix is to make sure that the conversion is performed the same back and forth, i.e. subtract 90 and convert to radians.

Another potential fix, and the one I recommend, is to not change to degrees and back at all. Instead, do the following:

private static final float ANGLE_FACTOR=90.0f;
public void setAngle(float theAngle){angle = theAngle;}
public float getAngle(){return angle;}
public float getImageAngle(){return Math.toDegrees(getAngle()+ANGLE_FACTOR);}

You then use this to set the angle

setAngle(Math.atan2(yDistance, xDistance));

And this for the force vector

force = angleToVector(getAngle());

And this to set the image angle:

image.setRotation(getImageAngle());

Alternately, you could also cache the image angle at the same time that you set the angle itself.

Third and final option: normalize the vector from the mouse coordinates (i.e. divide by the length of the vector, if it is not zero), calculate the image angle from that, then you don't have so many conversions all over the place.

• Thanks, I'm almost done work so when I get home I'll try that out and get back to you :) Aug 8, 2012 at 19:28