Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Bullet move in certain direction based on mouse

This thread is locked; no one can reply to it. rss feed Print
Bullet move in certain direction based on mouse
Mindsc2tv
Member #14,277
May 2012

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
Member #10,969
May 2009
avatar

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
Member #14,277
May 2012

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

Stas B.
Member #9,615
March 2008

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
Member #14,277
May 2012

Now I see. "sp" stands for speed?

Edgar Reynaldo
Member #8,592
May 2007
avatar

@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
Member #14,277
May 2012

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
Second in Command
February 2005
avatar

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?

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Edgar Reynaldo
Member #8,592
May 2007
avatar

SpectreNectar
Member #10,969
May 2009
avatar

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
Member #14,277
May 2012

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.
Member #9,615
March 2008

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
Member #8,592
May 2007
avatar

Mindsc2tv
Member #14,277
May 2012

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

Stas B.
Member #9,615
March 2008

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
Member #14,277
May 2012

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
Member #8,592
May 2007
avatar

Mindsc2tv
Member #14,277
May 2012

      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.
Member #9,615
March 2008

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
Member #14,277
May 2012

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
Member #10,969
May 2009
avatar

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
Member #8,592
May 2007
avatar

@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
Member #14,277
May 2012

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

Stas B.
Member #9,615
March 2008

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
Member #8,592
May 2007
avatar

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

Go to: