Jump to content

  • Log In with Google      Sign In   
  • Create Account

Limiting Bullets and stopping spamming - DirectX


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 v0rtexza   Members   -  Reputation: 125

Like
0Likes
Like

Posted 30 June 2012 - 12:14 PM

Hey all, I am making a simple sidescroller space shooter and have encountered a problem. I do not know how to limit the amount of bullets adequately or control the difference between input times.

Here is the relevant code that I know is the problem.

I create space in memory for my bullet sprites and I set their default properties (according to my own class):

[source lang="cpp"]//bullet spritesconst int MAX_BULLETS = 20;SPRITE bullets [MAX_BULLETS];//set default propertiesfor (int j = 0; j < MAX_BULLETS;j++) { bullets[j].alive = false; bullets[j].startframe = 0; bullets[j].endframe = 1; bullets[j].delay = 10; bullets[j].x = 0; bullets[j].y = 0; bullets[j].height = 55; bullets[j].width = 16; bullets[j].columns = 1; bullets[j].vely = 6.0f; } imgBullet = LoadTexture("purplefire.tga"); if (!imgBullet) return false; player_shoot_timer = 0;[/source]

I then go onto set bullets to alive when I click space bar like so:

[source lang="cpp"]if (Key_Down(DIK_SPACE)) { //limit firing rate if ((int)timeGetTime() < player_shoot_timer + 100) return; player_shoot_timer = timeGetTime(); if (CurrentBullet >= MAX_BULLETS) CurrentBullet = 0; CurrentBullet++; bullets[CurrentBullet].alive = true; bullets[CurrentBullet].x = player.x + (player.width/2); bullets[CurrentBullet].y = player.y; }[/source]
But the above code is not adequately stopping me from shooting if I hold down for example space bar, any ideas on that?

Finally in my actual game loop, I render the bullets that are deemed "alive" or have been shot already:

[source lang="cpp"]for (int k = 0;k < MAX_BULLETS;k++) { if (bullets[k].isAlive() == true) { bullets[k].y -= bullets[k].vely; // Sprite_Animate(bullets[k].frame,bullets[k].startframe,bullets[k].endframe,1,bullets[k].starttime,bullets[k].delay); Sprite_Draw_Frame(imgBullet,bullets[k].x,bullets[k].y,bullets[k].frame,bullets[k].width,bullets[k].height,bullets[k].columns); } }[/source]

However the problem is that I can hold down spacebar and it will just keep rendering the bullets to that spot and once I finish the program/close it, I get the following error:

Unhandled exception at 0x61a659da (msvcr100d.dll) in Tile_Dynamic_Scroll.exe: 0xC0000005: Access violation reading location 0x4424aac2.

I am guessing this is because I am not resetting the bullets adequately but I can't figure out:

a) how to create a time between each fired bullet so that the user cannot spam spacebar, my current implementation does not work
b) Limit the amount of bullets fired and reset them accordingly.

(if any more code is needed, I will supply upon request as the entire project is largeish)

I do not want the complete answer but merely a nudge in the right direction, any help is appreciated.

Thanks, v0rtex

Sponsor:

#2 Madhed   Crossbones+   -  Reputation: 3134

Like
1Likes
Like

Posted 30 June 2012 - 02:50 PM

In the second code snippet you are always creating a bullet every 100ms even if MAX_BULLETS are already alive, that means the bullet are constantly being reset to the player's position.
As for the exception: Have you tried running the program in debug mode and pause when the exception happens?

#3 fastcall22   Crossbones+   -  Reputation: 4457

Like
2Likes
Like

Posted 30 June 2012 - 04:17 PM

In addition to Madhed's suggestion, your access violation is a buffer overrun:

    if (CurrentBullet >= MAX_BULLETS) CurrentBullet = 0;
    CurrentBullet++;

Recall that an array of N elements is named from 0 to N-1. If CurrentBullet == MAX_BULLETS-1, then the tested condition is false in the first line of this snippet. After executing the next line, CurrentBullet == MAX_BULLETS, which is an invalid index in the array bullets.
c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#4 fastcall22   Crossbones+   -  Reputation: 4457

Like
1Likes
Like

Posted 30 June 2012 - 04:27 PM

(Can't edit my post?!)

Any attempt to write to past the end of bullets will either cause your program to crash (best case), an unrelated bug to appear elsewhere (unfavorable), or behave exactly as expected (worst case).

Addendum to Madhed's suggestion:
You may want to consider searching for a dead bullet to create your new bullet as you may overwrite an existing living bullet.

Another consideration:
You might want to consider using [url=http://www.cplusplus.com/reference/stl/vector/]std::vector[/tt], which is a dynamically resizing array with additional safety checks in your debug build.
c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#5 v0rtexza   Members   -  Reputation: 125

Like
0Likes
Like

Posted 01 July 2012 - 01:15 AM

Wow lol, was focusing so much on the graphics and DirectX that I forgot something as simple as that. Thanks! My only last problem is that I do not know how to space input, so that for example when you click space. Only 1 shot is registered, at the moment whenever space is held down, my variable CurrentBullet (as seen in the listing above) continually increases as much as I click instead of only registering one click. Any ideas?

#6 fastcall22   Crossbones+   -  Reputation: 4457

Like
1Likes
Like

Posted 01 July 2012 - 01:37 AM

You'll need to move from this sort of logic:
if ( isKeyPressed( KEY_SPACE ) ) {
    // ...
}

To this (quickfix):
// Assume:  bool keySpaceIsHeld = false;
if ( isKeyPressed( KEY_SPACE ) ) {
    if ( !keySpaceIsHeld ) {
        keySpaceIsHeld = true;
        // ...
    }
} else
    keySpaceIsHeld = false;

However, this approach is tedious and the OS already provides this functionality. Since you're using win32, you can handle the WM_KEYDOWN message in your event loop and signal the object responsible for firing the bullet:

LRESULT CALLBACK wndproc( HWND h, INT msg, WPARAM wParam, LPARAM lParam ) { // (Guessing this declaration here)
    switch ( msg ) {
        case WM_KEYDOWN: {
            switch ( wParam ) {
                case VK_SPACE:
                    player->fireBullet();
                    break;
                // etc...
            }
        } break;

        // etc...
    }

    return DefWndProc( h, msg, wParam, lParam ); // 
}

c3RhdGljIGNoYXIgeW91cl9tb21bMVVMTCA8PCA2NF07CnNwcmludGYoeW91cl9tb20sICJpcyBmYXQiKTs=

#7 v0rtexza   Members   -  Reputation: 125

Like
0Likes
Like

Posted 01 July 2012 - 02:29 AM

Thanks fastcall22, I tried your first solution:

[source lang="cpp"] if (Key_Down(DIK_SPACE)) { //limit firing rate // if (GetTickCount() - player_shoot_timer > 100) return; //player_shoot_timer = GetTickCount(); if (!keySpaceIsHeld) keySpaceIsHeld = true; if (keySpaceIsHeld) { if (CurrentBullet == MAX_BULLETS -1) return; //CurrentBullet = Max Ammo, So Exit if (CurrentBullet < MAX_BULLETS) //If there are bullets available { bullets[CurrentBullet].alive = true; bullets[CurrentBullet].x = player.x + (player.width/2); bullets[CurrentBullet].y = player.y; } } }[/source]

But It still does what it did and increases CurrentBullet a lot instead of by 1 upon each keypress. Editing my windows code to work with my main code sounds like a massive hassle as I would have to rewrite ALOT of my code... Sorry to bother man, you've been a lot of help!

#8 v0rtexza   Members   -  Reputation: 125

Like
0Likes
Like

Posted 01 July 2012 - 02:34 AM

Sorry as an addendum to my last post (as I can't edit!?)
After the second last bracket, I had:
[source lang="cpp"]}}else keySpaceIsHeld = false;}[/source]

#9 v0rtexza   Members   -  Reputation: 125

Like
0Likes
Like

Posted 01 July 2012 - 02:01 PM

Nevermind, got it working with the following:

I set a long variable to 0 that would hold the last time the player shot and then I did the following

[source lang="cpp"] if ((int)timeGetTime() < lastShot + 100) return; else {//shoot bullet}[/source]
Thanks everyone, for all your help!




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS