Realistic missile speed relative to ship velocity

I have a very basic Asteroids-ish demo. At the moment, no matter how fast the velocity of the ship is, the missiles travel at a constant velocity: -

missile_velocity = new Vector2D(MISSILE_SPEED, MISSILE_SPEED);

Now, if the ship was always facing in the direction of motion when firing, it would be simple enough with: -

missile_velocity = new Vector2D(MISSILE_SPEED + theShip.getVX(), MISSILE_SPEED + theShip.getVY());

But…since this is Asteroids-alike, the ship could be travelling in one direction and facing in another direction, which leads to very odd results - such as if the ship was facing 180 degrees of the direction of travel, the missile speed is still MISSILE_SPEED + Ship Speed when I assume it should be either a steady rate or halved.

So, what to do? My math isn’t great. The ship’s motion is worked out with: -

if (isThrusting) {
acceleration.x = THRUST_POWER * theMechanics.cosLookupTable[(int)angle - 1];
acceleration.y = THRUST_POWER * theMechanics.sinLookupTable[(int)angle - 1];
} else {
acceleration.x = 0.0;
acceleration.y = 0.0;
}
velocity.x += acceleration.x;
velocity.y += acceleration.y;
position.x += velocity.x;
position.y += velocity.y;

Any help would be great :slight_smile:

Hmm…nevermind, I’ve just seen the post below mine. Fortuitous! :smiley:

Nope, that doesn’t seem to work - can someone explain it in layman’s terms?

Is it some kind of homework and all the class will pop here?

Anyway there is already a solution in the other thread.

Nope, although I surely understand the stress of having to look at two similar threads. How dreadful for you.

Anyway…

I’m writing a small vector game using no external assets, is all. Unlike the other guy, I’m using a “wrap-around” world. What confuses me is that the solution in the other thread produces strange results. I initially have this: -


public Missile(Mechanics theMech, Ship theShip, int GFX_X, int GFX_Y, Color c) {
		angle = (-theShip.getAngle() + 180) % 360.0;
		if (angle < 0.0) { angle = angle + 360.0; }
		theMechanics = theMech;
		screen_X = GFX_X;
		screen_Y = GFX_Y;
		theColour = c;

		velocity = new Vector2D(MISSILE_SPEED, MISSILE_SPEED);

		startPosition = new Vector2D((theShip.getHeight() / 2) * theMechanics.sinLookupTable[(int)angle - 1] + theShip.getPosX(), (theShip.getHeight() / 2) * theMechanics.cosLookupTable[(int)angle - 1] + theShip.getPosY());
		endPosition = new Vector2D(10 * theMechanics.sinLookupTable[(int)angle - 1] + startPosition.x, 10 * theMechanics.cosLookupTable[(int) angle - 1] + startPosition.y);
}

…which works well enough. But obviously, the missile speed is constant. The solution from the other thread appears to be: -


public Missile(Mechanics theMech, Ship theShip, int GFX_X, int GFX_Y, Color c) {
		angle = (-theShip.getAngle() + 180) % 360.0;
		if (angle < 0.0) { angle = angle + 360.0; }
		theMechanics = theMech;
		screen_X = GFX_X;
		screen_Y = GFX_Y;
		theColour = c;

		velocity = new Vector2D(theShip.getVX() + theMech.cosLookupTable[(int) angle - l] * MISSILE_SPEED, theShip.getVY() + theMech.sinLookupTable[(int) angle - l] * MISSILE_SPEED);

		startPosition = new Vector2D((theShip.getHeight() / 2) * theMechanics.sinLookupTable[(int)angle - 1] + theShip.getPosX(), (theShip.getHeight() / 2) * theMechanics.cosLookupTable[(int)angle - 1] + theShip.getPosY());
		endPosition = new Vector2D(10 * theMechanics.sinLookupTable[(int)angle - 1] + startPosition.x, 10 * theMechanics.cosLookupTable[(int) angle - 1] + startPosition.y);
}

…produces odd results as well. If the ship is stationary with an angle of 0.0, the missiles travel very slowly at an angle of about 320 degrees (11 0’clock-ish). If the ship has a forward velocity at this angle, the missiles appear at 180 degrees (aft of the ship). Rotating and firing produces even stranger results.

Have I got my math mixed up above?

My thread wasn’t homework, I am waaay to old for that.

It looks like you are working in degrees, the java sin/cos methods work in radians. How are you populating your lookup tables?

When I fire, I do the following:

                GameVector shotV = new GameVector(shipObj.velocity);
                GameVector shotV2 = new GameVector();
                shotV2.setAngle(Math.toRadians(angle));   /* <---- this is the angle the ship is facing */
                shotV2.setLength(shotSpeed);              /* <---- pre-defined speed for the shots   */
                shotV2 = shotV.add(shotV2);
                shot.setThrust(shotV2.angle, shotV2.length); /* <---- this just replaces the values on the shot's movement vector */

In my vector class, I do the addition as follows:

	public GameVector(double x, double y) {
		setPosition(x, y);
	}
	public void setPosition(double x, double y) {
		this.x = x;
		this.y = y;
		angle = Math.atan2(y, x);
		length = Math.sqrt(x*x+y*y);
	}
	public GameVector add(GameVector v) {
		return new GameVector(x+v.x, y+v.y);
	}
	public void setAngle(double angle) {
		setPolar(angle, this.length);
	}
	public void setLength(double length) {
		setPolar(angle, length);
	}
	public void setPolar(double angle, double length) {
		this.angle = angle;
		this.length = length;
		x = Math.cos(angle)*length;
		y = Math.sin(angle)*length;
	}

EDIT - including the setAngle and setLength methods from my vector class

Hi, thanks for replying :slight_smile:

My lookup tables are populated as follows: -


for (int s = 0; s < sinLookupTable.length; s++) {
    sinLookupTable[s] = Math.sin(Math.toRadians(s));
}
for (int c = 0; c < cosLookupTable.length; c++) {
    cosLookupTable[c] = Math.cos(Math.toRadians(c));
}

I’ll have a look at your code tonight - I’m clearly doing something wrong :smiley:

I don’t know if it’s the cause of your problem, but this line

angle = (-theShip.getAngle() + 180) % 360.0;

is a bit strange. If the missile is supposed to be moving in the direction that the ship is pointing, then why is ‘angle’ not equal to ‘theShip.getAngle()’?

Also, you’re going to run into problems here if ‘angle’ is close to zero:

theMechanics.sinLookupTable[(int)angle - 1]

Another thought, are you using the value of ‘endPosition’ for anything? If you want to know when to delete the missile, it’s probably easier to count the number of seconds it’s been alive for or the distance it’s moved rather than trying to keep track of its end point. Floating-point errors mean that it’s very unlikely that the missile will ever hit its end point exactly.

When you create a missile, try printing (System.out.println) its angle, position and velocity, and the ship’s angle, position and velocity, and make sure they are consistent with what you are seeing on the screen.

Simon