How to implement a simple bullet trajectory

I searched and searched and although it's a fair simple question, I don't find the proper answer but general ideas (which I already have).

I have a top-down game and I want to implement a gun which shoots bullets that follow a simple path (no physics nor change of trajectory, just go from A to B thing).

a: vector of the position of the gun/player. b: vector of the mouse position (cross-hair). w: the vector of the bullet's trajectory.

So, w=b-a. And the position of the bullet = [x=x0+speedtimenormalized w.x , y=y0+speed*time * normalized w.y].

I have the constructor:

public Shot(int shipX, int shipY, int mouseX, int mouseY) {
//I get mouse with Gdx.input.getX()/getY()
...

this.shotTime = TimeUtils.millis();

this.posX = shipX;
this.posY = shipY;

//I used aVector = aVector.nor() here before but for some reason didn't work
float tmp = (float) (Math.pow(mouseX-shipX, 2) + Math.pow(mouseY-shipY, 2));
tmp = (float) Math.sqrt(Math.abs(tmp));

this.vecX = (mouseX-shipX)/tmp;
this.vecY = (mouseY-shipY)/tmp;
}


And here I update the position and draw the shot:

public void drawShot(SpriteBatch batch) {

//position = positionBefore + v*t
...
}


Now, the behavior of the bullet seems very awkward, not going exactly where my mouse is (it's like the mouse is 30px off) and with a random speed. I know I probably need to open the old algebra book from college but I'd like somebody says if I'm in the right direction (or points me to it); if it's a calculation problem, a code problem or both. Also, is it possible that Gdx.input.getX() gives me non-precise position? Because when I draw the cross-hair it also draws off the cursor position.

Sorry for the long post and sorry if it's a very basic question. Thanks!

In shoot function you can find angle between player and mouse position

deltaX = mouseX - shipX
deltaY = mouseY - shipY
angle = atan2(deltaY, deltaX)


Then you can use that angle to update bullet position:

posX = posX + speed * deltaTime * cos(angle)
posY = posY + speed * deltaTime * sin(angle)

• For a searchable term, try polar coordinates - very useful in general for things in game programming. – Chaosed0 Jun 12 '14 at 20:31

I use the same calculation and I don't have the same issue, perhaps the error is with the Gdx.input.getX(). I am not familiar with libgdx, so I can't comment directly on this. Maybe you can test this by shooting at an exact known location. One suggestion would be to color a pixel at say (300, 300), and shoot directly on it then check what the mouseX, and mouseY values.

I like how you calculate the trajectory separate from the draw since this operation only needs to be done once. One tip, the result of any number squared will never be negative so there is no need to use Math.abs().

One more suggestion, if you are using a pointy image, like an arrow, as opposed to something round, like a fireball, you can rotate the image to match the trajectory. I took the liberty of rewriting something things for clarity of intent. You can generate a rotation angle and then rotate the sprite with this value.

private float rotation;
...

public Shot(int shipX, int shipY, int mouseX, int mouseY){
this.posX = shipX;
this.posY = shipY;

int xTrajectory = mouseX - shipX;
int yTrajectory = mouseY - shipY;
float length = (float)Math.sqrt(xTrajectory*xTrajectgory + yTrajectory*yTrajectory);

this.vecX = xTrajectory/length;
this.vecY = yTrajectory/length;

float angle = (float)Math.acos(vecX);

if (yTrajectory > 0) {
rotation = (float)Math.toDegrees(angle);
}
else {
rotation = (float)Math.toDegrees(-angle);
}
}

...
sprite.setRotation(rotation);


EDIT: I was curious so I looked this up. If you are using a custom cursor, you can set the hotspot. If the hotspot is off this could be the error you are seeing. With a cross hair the hot spot should be in the center, as opposed to a arrow, where the hot spot should be at the tip.