Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Trying to make projectiles

This thread is locked; no one can reply to it. rss feed Print
Trying to make projectiles
DuncanShine
Member #17,479
March 2020

I'm trying to make projectiles that travel outwards from the player in the direction of the mouse until they hit something, but I can't figure out how to do it.

I've tried using some vector physics but it's not working the way I want it to.

void Weapons::fire() {
    this->bullet.x -= this->dx + gun.speed * acos(mouse.radians * pi / 180);
    this->bullet.y -= this->dy + gun.speed * asin(mouse.radians * pi / 180);
}

DanielH
Member #934
January 2001
avatar

You are changing position at fire. Is this called once or at each logic update?

What about adding a velocity (and maybe an acceleration) variable?
Set velocity and start position at time of shoot.
Then update position each logic frame.

#SelectExpand
1// this function is called once 2void Weapons::fire() { 3 this->bullet.x = // set here 4 this->bullet.y = // set here 5 this->bullet.vx = gun.speed * acos(mouse.radians * pi / 180); 6 this->bullet.vy = gun.speed * asin(mouse.radians * pi / 180); 7} 8 9// this function is called each logic update until bullet is dead 10void Weapons::update() { 11 // update velocity before or after movement (gravity, etc...) 12 // check collision, timeout, etc... 13 14 this->bullet.x += this->bullet.vx; 15 this->bullet.y += this->bullet.vy; 16}

Not sure what dx and dy were so left out. You can put back if needed.

DuncanShine
Member #17,479
March 2020

The dx and dy were the difference between the coordinates of the player & bullet - i copied most of the code over from an earlier part so it might have been wrong.

Anyway, I adapted the code - the bullet moves now, but for some reason it only goes in one direction regardless of where the mouse is pointed.

[EDIT] changing the filled circle into a bitmap fixed it for some reason

Mark Oates
Member #1,146
March 2001
avatar

Think about the bullet as a separate object. When the player fires a bullet, a new bullet is created, and is set to be moving in a direction (you should call this velocity).

Later, you update the position of all the bullets that have been created (you'll need to have them in a list).

Notice that the position of the bullet and the position of the player have nothing to do with each other. Except when the bullet is created, more on that below.

With that in place, the question then becomes "how do I set the correct direction/velocity for the bullet when it's created". For that, you'll need to know the "world position" of the mouse relative to the player position. Subtracting the mouse world position from the player position souls give you the direction vector. With that, you normalize it and then multiply by whatever speed you want yhe bullet to travel.

DuncanShine
Member #17,479
March 2020

Okay, now creating the bullet is done, I was wondering if I could put these bullets into a vector, then use a for loop to draw and update all the bullets?

DanielH
Member #934
January 2001
avatar

Using a vector would be fine.

#SelectExpand
1void fire() 2{ 3// add one bullet to vector+ 4// set a limit on how fast and how many bullets you can fire 5} 6 7void update() 8{ 9// process and set to dead if needed 10// call purge at end of updates 11} 12 13void purge() 14{ 15// remove all dead bullets. Remember to update iterator as needed. 16// do not use a simple for loop and delete/erase at point of iterator. 17// leaves dangling iterators 18} 19 20void draw() 21{ 22}

Frank Drebin
Member #2,987
December 2002
avatar

That's the way I do it:

// init bullet
bullet.x = player.x;
bullet.y = player.y;
bullet.angle = atan2(mouse.y-player.y,mouse.x-player.x);

// move bullet
bullet.x += speed*cos(bullet.angle);
bullet.y += speed*sin(bullet.angle);

DuncanShine
Member #17,479
March 2020

It all seems to work now, but i'm not sure how to remove the bullet after it leaves the screen
Ideally it would work like this

        if (bullet_vector[i].x > WIDTH || bullet_vector[i].x < 0 || bullet_vector[i].y > HEIGHT || bullet_vector[i].y < 0) {
          //bullet is destroyed here
        }

Mark Oates
Member #1,146
March 2001
avatar

The most robust technique is a two step process. Add a boolean flag on the bullet (can_be_destroyed). In your conditional you have set the flag to true.

Later, during "cleanup", simply remove the flagged elements from the vector

for (int i=0; i<bullet_vector.size(); i++)
{
  if (bullet_vector[i].can_be_destroyed)
  {
    bullet_vector.erase(bullet_vector.begin() + i);
    i--;
  }
}

DuncanShine
Member #17,479
March 2020

I tried this method but it returns an error that the "vector subscript is out of range"

Go to: