Problem with mouse firing. (probably math related?)

In the game i am making i have run into a problem when it comes to using the mouse to fire bullets.
The bullets go in a completely different direction then what i want them to do.
You have probably had people with this problem several times, i have looked trough 3 of the posts on JG, but cant find an answer that helps me in there.

I am doing this in LibGDX.

These are the related methods;

Part of the InputProcessor in Player.java. (mouseMoved because i dont want to click at the moment, for testing.)


	public boolean mouseMoved(int screenX, int screenY) {
		this.mouseX = screenX - position.x / 2;
		this.mouseY = screenY - position.y / 2;
		this.dir = Math.atan2(mouseY, mouseX);	
		shoot();
		return false;
	}

Shoot method in Player.java


public void shoot() {
	bullets.add(new Bullet(new Vector2(position.x, position.y), 350, dir));
	}

Constructor in Bullet.java


	double newX, newY;

	public Bullet(Vector2 position, int SPEED, double dir) {
		this.position = new Vector2(position.x, position.y);
		Math.cos(dir);
		this.newX = SPEED * Math.cos(dir);
		this.newY = SPEED * Math.sin(dir);
		}

Update method in Bullet.java


public void update() {
		position.x += newX * Gdx.graphics.getDeltaTime();
		position.y += newY * Gdx.graphics.getDeltaTime();
	}

I am copying TheChernos way of doing it, and it works when in the game i have created in his tutorial.
These are the related stuff in that code. The difference i can see if where deltatime is added.


private void updateShooting() {
		if (Mouse.getB() == 1) {
			double dx = Mouse.getX() - Game.getWindowWidth() / 2;
			double dy = Mouse.getY() - Game.getWindowHeight() / 2; 
			double dir = Math.atan2(dy, dx);
			shoot(x, y, dir);
			}
	}

/////////////

public Projectile(int x, int y, double dir) {
		xOrigin = x;
		yOrigin = y;
		angle = dir;
		this.x = x;
		this.y = y;
		Math.cos(angle);		
		nx = speed * Math.cos(angle);
		ny = speed * Math.sin(angle);
	}

//////////
public void move() {
		x += nx;
		y += ny;
	}

I also tried looking at ForeignGuyMikes Asteroids tutorial, but couldnt get that to work either.

Java2D works with the origin in the top left while I think the origin for LibGDX is the bottom left. You’ll need to draw everything the opposite as in theChernoProjects’s tutorials.

Why are you dividing the player position by 2 in mouseMoved? I assume you want the vector from the player to the mouse so it should just be “screenX - position.x”. The reason the window height and width are divided in 2 in TheCherno’s code is because he is taking the vector from the midpoint of the screen (width/2 , height/2) to the mouse.

The coordinate system should not matter as long as it is consistent between the mouse coords and the drawing coords.

opiop65:
And how would i get on with doing that? I am not even a novice when it comes to this kind of math…

kramin42:
I thought that would make the shots come from the characters position, you are right. And i believe i had removed that on an earlier try with this method.

edit
So, after that brainfart i was able to make it half correct. It fires correctly on the X-axis, but is inverted on the Y-axis.
I subtracted the width and height to the x and y to invert them from libgdx format.

edit
So, this morning i had a fresh look at it, and since only the Y-axis was inverted i changed this method in Bullet.java.


public void update() {
		position.x += dx * Gdx.graphics.getDeltaTime();
		position.y += dy * Gdx.graphics.getDeltaTime();
	}

To subtract on the Y-axis instead.


public void update() {
		position.x += dx * Gdx.graphics.getDeltaTime();
		position.y -= dy * Gdx.graphics.getDeltaTime();
	}

And it works.

edit

Uhm. Nope it doesnt. It only works on some areas of the map. :confused:
edit

It only works in the center of the map, if i move the player around it skews the direction.
I tried putting the bullet and mouse positions to constants and it only happens when the player positions changes.

I am still having this problem. :confused:

Can you describe your problem in more detail and/or perhaps post a little movie? For example:
Is the problem getting worse the farther you are from the center of the screen? That should indicate that the center is part of the bullet equation somehow.
If the shooting works when the player is standing still I´m wondering if something´s happening with the player update that messes up the bullets direction.
How huge is the error? Is it almost correct or is it shooting wildly all around the screen when the player is moving? And is the error increasing when you move around or is it constant?

It also seems that you have changed a lot of code since the first post so perhaps posting a code update would be a good idea. In any case it would be nice to see the entire player class and bullet class.

The game is made in LibGDX, it uses maps made in Tiled.

The problem is that the bullet direction gets skewed when i move from the center of the map, the more from it i go, the more it differ, at the top of the map it fires down to the left corner if i try to fire straight up.

Player class, removed stuff like inventory and collision.
The Entity class has collision and such.

I’ll see if i can get a movie made or if i’ll just upload the game.

edit
Here is a video of the error.

And here is the actual game as a jar.

/edit




double musX, musY, dir;
int mapHeight, mapWidth;

public Player(Vector2 position, float rotation, int SPEED, String textString, TiledMapTileLayer colLayer, int cols, ArrayList<Bullet> bullet) {
		super(position, rotation, SPEED, textString, colLayer, cols);
		this.bounds = new Rectangle(position.x, position.y, 32, 32);
		this.bullets = bullet;	
		this.mapHeight = 320;
		this.mapWidth = 480;
		}
public boolean keyDown(int keycode) {
		switch(keycode){
		case Keys.W:
			velocity.y = 1;
			break;
		case Keys.S:
			velocity.y = -1;
			break;
		case Keys.A:
			velocity.x = -1;
			break;
		case Keys.D:
			velocity.x = 1;
			break;
		case Keys.NUM_1:
			inventory = 1;
			updateInventory();
			break;
		case Keys.NUM_2:
			inventory = 2;
			updateInventory();
			break;
		default:
			break;
		
		}	
		return true;
	}

	@Override
	public boolean keyUp(int keycode) {
		switch(keycode){
		case Keys.W:
			if(velocity.y == 1)
				velocity.y = 0;
			break;
		case Keys.S:
			if(velocity.y == -1)
				velocity.y = 0;
			break;
		case Keys.A:
			if(velocity.x == -1)
				velocity.x = 0;
			break;
		case Keys.D:
			if(velocity.x == 1)
				velocity.x = 0;
			break;
		default:
			break;
		
		}
		return true;
	}
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		switch(button){
				case Buttons.LEFT:
					this.musX = screenX - (mapWidth - position.x);
					this.musY = screenY - (mapHeight - position.y);
					this.dir = Math.atan2(mouseY, mouseX);
					
					shoot();
		break;
		}
		return true;
	}
public void shoot() {
	bullets.add(new Bullet(new Vector2(position.x, position.y), 350, dir));
}

Bullet class


public class Bullet{
	
	public Vector2 position;
	Vector2 velocity;
	int SPEED;
		
	double dx;
	double dy;
	int mapWidth, mapHeight;
	double dir;
	Texture bulletTexture = new Texture("img/bullet.png");
	
	
	public Bullet(Vector2 position, int SPEED, double dir) {
		this.position = new Vector2(position.x, position.y);
		this.SPEED = SPEED;
		Math.cos(dir);
		this.dx = SPEED * Math.cos(dir);
		this.dy = SPEED * Math.sin(dir);
		}
public Texture getBulletTexture() {
	return bulletTexture;
}
public void update() {
	
		position.x += dx * Gdx.graphics.getDeltaTime();
		position.y -= dy * Gdx.graphics.getDeltaTime();		
	}
}

I think this is messing it up:

this.musX = screenX - (mapWidth - position.x);
this.musY = screenY - (mapHeight - position.y);
this.dir = Math.atan2(mouseY, mouseX);

and should be

this.musX = screenX - position.x;
this.musY = screenY - position.y;

instead, otherwise the direction won´t be right. And there´s a typo in Math.atan2. I´m guessing it´s supposed to be Math.atan2(musY, musX) instead?

In LibGdx the x and y starts at the lower left, and not top left, which the mouse and other java does. Thus i added that stuff to make them equal, i have noticed though that i dont need to add the width for the x since its 0 at that side anyways. But the problem is still there.

Disregard the mouseX / musX discrepancies, i write some stuff in swedish and i thought i had changed all the mus to mouse in my post so people wont get confused.

Anyways, i have checked the positions more and more, and it seems the problem lies somewhere in the way coordinates works for the maps loaded into LibGdx.
Check this picture;

The dots are at (0,0), (240,160)(center) and (320,480) top right.
I have also added a if player is outside those bounds, don’t move there, and in the picture i am moving upwards, but cant get further then that.

But then the firing should be all right if i am within those bounds, but it isnt. :confused:

Woop!
I fixed it.
I found an answer online that converted the mouse position on the screen to the position ingame.
With that it is working as intended. And since it gives the coordinates in the same fashion i do not need to invert the numbers.


	Vector3 test;
	@Override
	public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		switch(button){
				case Buttons.LEFT:
					test = new Vector3(screenX, screenY, 0);
					camera.unproject(test);
					this.musX = test.x - position.x;
					this.musY = test.y - position.y;
					this.dir = Math.atan2(musY, musX);					
					shoot();
		break;
		}
		return true;
	}


Answer from http://gamedev.stackexchange.com/questions/60703/libgdx-how-to-get-mouse-position-relative-to-a-tiled-map

Awesome! I love that feeling when you manage to sort out problems!

…And being from Sweden myself I know what “mus” means. :wink: God jul! That’s “Merry Christmas” to y’all! :slight_smile: