0
\$\begingroup\$

I'm coding a C++ SDL game and now I got a problem with my bullets. If I shoot, bullets should fly away in a straight line according to the player's angle. That's ok but how can I copy multiple bullets to the screen at the same time? For example, if I had an uzi or a machine gun and wanted to copy up to 30 bullets at the same time.

Currently I'm only getting one bullet on the screen at a time and when I hit space, it just deletes my first bullet and copies the second bullet.

Notice that the variable bulletFire is set to '2' when I hit space (fire), so its main object is to keep bullets on the screen when space is up.

In the class Shooting I have following lines of code:

class Shooting
{
public:
const Shooting()
{
    if (selectedWeapon == 4 && fire || selectedWeapon == 4 && bulletFire == 2 || selectedWeapon == 6 && fire || selectedWeapon == 6 && bulletFire == 2)
    {
        BulletMovement();
    }
    else BulletStart();
}

In BulletMovement():

    if (current == 1)
    {
        bullet[0].x = 1893;
        bullet[0].y = 673;
        bullet[0].w = 3;
        bullet[0].h = 4;
        ClipBullet[0].x += BulletSpeed * (cos((currentAngle) * 3.14159 / 180));
        ClipBullet[0].y += BulletSpeed * (sin((currentAngle) * 3.14159 / 180));
        ClipBullet[0].w = bullet[0].w;
        ClipBullet[0].h = bullet[0].h;
    }
....
if (current == 30)
    {
        bullet[29].x = 1893;
        bullet[29].y = 673;
        bullet[29].w = 3;
        bullet[29].h = 4;
        ClipBullet[29].x += BulletSpeed * (cos((currentAngle) * 3.14159 / 180));
        ClipBullet[29].y += BulletSpeed * (sin((currentAngle) * 3.14159 / 180));
        ClipBullet[29].w = bullet[29].w;
        ClipBullet[29].h = bullet[29].h;
    }

In BulletStart() I keep moving my bullets' startpoint next to the pistol if I haven't shot it yet:

static void BulletStart()
{
        if (currentBulletUpdate[1] == '0')
        {
            ClipBullet[0].x = (clipPlayer.x + 50 /*51*/) + 60 * cos((playerAngle) * 0.0174532925);
            ClipBullet[0].y = (clipPlayer.y + 24.5 /*51*/) + 60 * sin((playerAngle) * 0.0174532925);
        }
....
        if (currentBulletUpdate[30] == '0')
        {
            ClipBullet[29].x = (clipPlayer.x + 50 /*51*/) + 60 * cos((playerAngle) * 0.0174532925);
            ClipBullet[29].y = (clipPlayer.y + 24.5 /*51*/) + 60 * sin((playerAngle) * 0.0174532925);
        }

Then I have BulletCycle() which increases the variable current when I shoot:

static void BulletCycle()
{
    if (selectedWeapon == 4 && bulletFire == 2 || selectedWeapon == 6 && bulletFire == 2)
    {
        if (fire) current = 1;

        if (current == 1)
        {
            currentBulletUpdate[1] = { 1 };
            CopyBullets();
            if (ClipBullet[0].x <= WINDOW_WIDTH + 1000 || ClipBullet[0].y <= WINDOW_HEIGHT + 1000) CopyBullets();
            if (fire) current = 2;
            else if (ClipBullet[0].x >= WINDOW_WIDTH || ClipBullet[0].y >= WINDOW_HEIGHT) currentBulletUpdate[1] = { 1 };
        }

        if (current == 2)
        {
            currentBulletUpdate[2] = { 1 };
            if (fire) current = 3;
            if (ClipBullet[1].x <= WINDOW_WIDTH + 1000 || ClipBullet[1].y <= WINDOW_HEIGHT + 1000) CopyBullets();
            if (ClipBullet[1].x >= WINDOW_WIDTH || ClipBullet[1].y >= WINDOW_HEIGHT) currentBulletUpdate[2] = { 1 };;
        }
....
            if (current == 30)
        {
            currentBulletUpdate[30] = { 1 };
            if (fire) current = current = 1;
            if (ClipBullet[29].x <= WINDOW_WIDTH + 1000 || ClipBullet[29].y <= WINDOW_HEIGHT + 1000) CopyBullets();
            if (ClipBullet[29].x >= WINDOW_WIDTH || ClipBullet[29].y >= WINDOW_HEIGHT) currentBulletUpdate[30] = { 0 };;
        }

And finally I copy my bullets in CopyBullets():

static void CopyBullets()
{
    if (fire)
    {
        currentBulletAngle = bulletAngle;
        if (left) currentBulletAngle -= 0;
        if (right) currentBulletAngle += 0;
    }

    if (currentBulletUpdate[1] == '1')
    {
        SDL_RenderCopyEx(rend, texture, &bullet[0], &ClipBullet[0], currentBulletAngle, NULL, SDL_FLIP_NONE);
    }
    if (currentBulletUpdate[2] == '1')
    {
        SDL_RenderCopyEx(rend, texture, &bullet[1], &ClipBullet[1], currentBulletAngle, NULL, SDL_FLIP_NONE);
    }
....

    if (currentBulletUpdate[30] == '1')
    {
        SDL_RenderCopyEx(rend, texture, &bullet[29], &ClipBullet[29], currentBulletAngle, NULL, SDL_FLIP_NONE);
    }

And notice all this code is in the while loop in int main(); I just cannot find any possible errors, so please help me.

\$\endgroup\$
  • 1
    \$\begingroup\$ Why are you not using array loops instead of an if with 30 branches \$\endgroup\$ – bl4ckb0ne Oct 10 '17 at 15:41
  • \$\begingroup\$ Because if we take for example BulletMovement() and I've shot 7 bullets with my machine gun. Then I need to move all those 7 bullets simultaneously as long as they are > WINDOW_WIDTH. I cant do that if I replace my Ifs with loops. Or can I? \$\endgroup\$ – Sandaalit Oct 10 '17 at 19:00
  • 3
    \$\begingroup\$ I think your approach of the problem is wrong, you should store your bullets in an array, and update them independently of the others. Here there is clearly a problem with your copy function \$\endgroup\$ – bl4ckb0ne Oct 10 '17 at 19:04
1
\$\begingroup\$

I'm not sure I can find your problem in the current code, but you could clean it up.

A lot of places you have 30 times exactly the same code with just different bullet id's. You should make a subroutine with the id as parameter for those places. A few places only 29 repeats, this is probably the most likely place for the error.

if (currentBulletUpdate[1] == '0') {
    ClipBullet[0].x = (clipPlayer.x + 50 /*51*/) + 60 * cos((playerAngle) * 0.0174532925);
    ClipBullet[0].y = (clipPlayer.y + 24.5 /*51*/) + 60 * sin((playerAngle) * 0.0174532925);
}
...

to

ClipIt(0);
ClipIt(1);
...
ClipIt(30);

When you have done that refactoring, you will realise that there might be a way to update the bullets individually in a loop instead.

for (int cnt = 0; cnt < 30; cnt++)
  ClipIt(cnt);

Now you have reduced your problem from 4 lines * 30 = 120 lines to just 2 lines of code making the program easier to reason about.

Treating each bullet individually instead of coping them to a new position not only saves you the copying but also makes it easier to identify which one is wrong.

Though you will in this design have to keep check on which bullets are active so you know where to place new bullet in the array.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.