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:

#SelectExpand
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:

#SelectExpand
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);

Umm, what's this about? Is Dir your name for velocity?

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.

Umm, what's this about? Is Dir your name for velocity?

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.

Your old code:

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);
      }

#SelectExpand
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);
      }

Thread #610197. Printed from Allegro.cc