Bullet move in certain direction based on mouse
Mindsc2tv

Hello. I'm trying to make a side shooting game and I've encountered a problem. I'm trying to make a bullet moving in certain direction based on mouse position. Was thinking for hours about this and I can't figure it out. My bullet update code looks like :

[code] if(this->bullDirection)
{
x += velX * dirX;
y += velY * dirY;
}
else
{
x -= velX * dirX;
y += velY * dirY;
}[/code]

Now it will shoot in two directions based on which side is player facing (left or right) changing only x. Hope you can help me, I should sent my game project to lecturer soon, so I hope you will help me soon(ish).

SpectreNectar

Would you like the bullet to move towards the mouse or do you want it to move in a direction depending on where the cursor is on screen? Maybe relative to a point?

Here's how to get the direction to the cursor from a point:

double dir = atan2( point_y-mouse_y, mouse_x-point_x )*180.0/ALLEGRO_PI;
(remember to check if the points are equal)

If this isn't what you wanted please clarify

Edit:
Oh yes by the way you might need these as well:

double velocity_x =  sp*cos(dir*ALLEGRO_PI/180.0);
double velocity_y =  -sp*sin(dir*ALLEGRO_PI/180.0);


Mindsc2tv

I would like to move bullet in the direction of the mouse pointer, not to the exact point :-).

Stas B.
Mindsc2tv said:

I would like to move bullet in the direction of the mouse pointer, not to the exact point :-).

That's what his code does.

Mindsc2tv

Now I see. "sp" stands for speed?

Edgar Reynaldo

@SpectreNectar - why do you convert to allegro degrees and then back? Just use radians....

double bullet_direction = atan2(mousey - bullety , mousex - bulletx);

bulletx += speed*cos(bullet_direction);
bullety += speed*sin(bullet_direction);


Mindsc2tv

Hm, it's not working for me, but I'm 99% sure I've did something wrong. The bullet is going only into two directions; left or right. Here's my code:

Bullet spawn:

1Bullet *bullet = new Bullet (player->GetX() + 10, player->GetY()+15); 2double dir = atan2(pos_y - bullet->GetY() , pos_x - bullet->GetX()); 3bullet->SetDirX(dir); 4bullet->SetDirY(dir); 5//bullet->bullDirection = !player->animationRow; 6objects.push_back(bullet);

Bullet update:

2void Bullet:: Update() 3{ 4 //if(this->bullDirection) 5 //{ 6 //x += dirX; 7 //y += dirY ; 8 9 x += velX*cos(dirX); 10 y += velY*sin(dirY); 11 //} 12 //else 13 //{ 14 //x -= velX * dirX; 15 //y += velY * dirY; 16 //} 17 if(x>WIDTH || x< 0) 18 Collided(BORDER); 19}

Arthur Kalliokoski
Mindsc2tv said:

I would like to move bullet in the direction of the mouse pointer, not to the exact point :-).

You mean you want the bullet to go toward the mouse pointer, but not stop there?

Edgar Reynaldo
Quote:

bullet->SetDirX(dir);
bullet->SetDirY(dir);


bullet->SetXVelocity(speed*cos(dir));
bullet->SetYVelocity(speed*sin(dir));


SpectreNectar

You have to remember to invert the y axis.

Screen co-ordinates go from the top left corner and down while atan2 goes to the right and upwards.

EDIT: Wait disregard this post.

Mindsc2tv

You mean you want the bullet to go toward the mouse pointer, but not stop there?

Exactly.

To be honest I don't know for what part dirX and dirY stands for, because this part of code was made by my buddy. I'll try to figure it out.

Stas B.
Mindsc2tv said:

Hm, it's not working for me, but I'm 99% sure I've did something wrong. The bullet is going only into two directions; left or right. Here's my code:

Your code appears to be correct.
What's the type of dirX\dirY?
Perhaps they're being rounded?

Edgar Reynaldo

It might be correct - but it is confusing. There should only be one direction variable, and only one speed variable, that you then split into component velocities...

Mindsc2tv

Those are double. Actually dirX = dirY and velX = velY. Names are different because of old system of shooting.

Stas B.

x += velX*cos(dirX);
y += velY*sin(dirY);


Should be:

x += speed*cos(dir);
y += speed*sin(dir);


I'm guessing what's going on is that velY = 0, so you only get left\right.

Mindsc2tv

Well, it's working, the Y is changing, but I think something's wrong with dir, because the bullets are not going towards the mouse .

Edgar Reynaldo

Post the code you're currently using.

Mindsc2tv
      if(ev.mouse.button &1)
{
pos_x = ev.mouse.x;
pos_y = ev.mouse.y;
Bullet *bullet = new Bullet (player->GetX() + 10, player->GetY()+15);
double dir = atan2(pos_y - bullet->GetY(), pos_x - bullet->GetX());
bullet->SetDirX(dir);
bullet->SetDirY(dir);
//bullet->bullDirection = !player->animationRow; //zeby bylo wiadomo w ktorym kierunku ma leciec kula
objects.push_back(bullet);
}


1void Bullet:: Update() 2{ 3 //if(this->bullDirection) 4 //{ 5 //x += dirX; 6 //y += dirY ; 7 velY = 1; //it's pretty hardcoded, I don't know why velY was 0 8 x += velX*cos(dirX); 9 y += velY*sin(dirY); 10 //} 11 //else 12 //{ 13 //x -= velX * dirX; 14 //y += velY * dirY; 15 //} 16 if(x>WIDTH || x< 0) 17 Collided(BORDER); 18}

Ignore the dirX and dirY, those have the same values, I'll change the names later. Same for velX and VelY.

Stas B.

Oh, atan2 is tricky.

double dir = atan2(pos_y - bullet->GetY() , pos_x - bullet->GetX());


Should be:

double dir = atan2(bullet->GetY() - pos_y , pos_x - bullet->GetX());


Mindsc2tv
Stas B. said:

Should be:

double dir = atan2(bullet->GetY() - pos_y , pos_x - bullet->GetX());

I've tried that and nope, that's not it :/. In this case bullets are going in opposite direction, f.e. if I have mouse in right corner, the bullets will go to the down corner.

SpectreNectar

See my last post. So you want to invert y in atan2() but also invert it in sin().

This is because:

.....................
.....................
.....................
.....................
................X....
.....................
.....................
...X.................
.....................
.....................

Is not the inverted version of:

.....................
.....................
.....................
.....................
...X.................
.....................
.....................
................X....
.....................
.....................

When it comes to angles. Something like this is:

.....................
.....................
.....X...............
.....................
.....................
.....................
.....................
..............X......
.....................
.....................

If I'm wrong then please disregard this post too.

EDIT Also, you're not testing if the points are identical. Using atan2 with 0 as both arguments is very similar to dividing with 0.
EDIT OK Disregard this post as well

Edgar Reynaldo

@Stas, no that's wrong. For the angle from Point1 to Point2 it should be :
angle = atan2(Point2.y - Point1.y , Point2.x - Point1.x);, so he's right.

Like I said before, DON'T use two variables for direction and speed.

direction = atan2(pos_y - bullet->GetY() , pos_x - bullet->GetX());

bullet->SetXVelocity(bullet->Speed()*cos(direction));
bullet->SetYVelocity(bullet->Speed()*sin(direction));


void Bullet::Update() {
x += xvel;
y += yvel;
}


@Spectre, no that's wrong. You don't need to invert anything. If you keep everything in screen coordinates or in world coordinates and then convert to screen coordinates later, you're fine.

Don't invert anything.

Mindsc2tv

@Edit
Nevermind, it's working, thank you so much!

Stas B.

Gosh. Just do what Edgar Reynaldo says...
Your velX and velY things probably just scale the result in a non-uniform way and mess it up.

Edgar Reynaldo

Oh, I think I see what you're doing wrong. You're mixing screen and world coordinates together. That's a no no.

So, you want to get the world coordinates of the mouse, and use those instead.
Something like :

// screen = world - camera;
// world = camera + screen;
if(ev.mouse.button &1)
{
pos_x = camera_x + ev.mouse.x;
pos_y = camera_y + ev.mouse.y;
Bullet *bullet = new Bullet (player->GetX() + 10, player->GetY()+15);
double dir = atan2(pos_y - bullet->GetY(), pos_x - bullet->GetX());
bullet->SetXVel(bullet->Speed()*cos(dir));
bullet->SetYVel(bullet->Speed()*sin(dir));
objects.push_back(bullet);
}