Jump to content
  • Advertisement
Sign in to follow this  
lvenonl

Key input delay

This topic is 1500 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys,

 

How do I put a delay on a key input in SDL? For example:

On a shoot 'em up game, if the player holds the fire button, there should be a delay between each missile created by his space ship.

 

 

Share this post


Link to post
Share on other sites
Advertisement

Operating systems and APIs can simulate 'key repeat', pretending and telling your application that the same key was repeatedly pressed. If I hold down the letter 'A', for example, usually the OS does: A <long pause>, AAAAAAAAAAAAAAAA

 

This is useful for text editing and things of that nature, and you can customize the delay in the OS and sometimes in the API itself, but it's not very useful for games. mellow.png

It doesn't really enforce that keypresses don't occur sooner or more frequently. This allows players to cheat by mashing their button a whole bunch to spam attacks faster than the developer intended, or to write programs to spam the button in software for them.

 

Really, the proper "game development" way of doing this is to code it yourself.

 

You don't really want "fire every time the key is pretended to be pressed by the operating system", what you really want is "fire every N millaseconds that the key is held down for".

 

So when SDL tells you, 'Spacebar was pressed', you mark 'bool spacebarIsHeld = true', and when they say 'Spacebar was released', you say, 'spacebarIsHeld = false'. (Or you can check the current state directly)

 

Then, on your programs time-controlled update tick, you say, "if enough time has passed, fire again".

void PlayerShip::Update(float timePassedInSeconds)
{
     accumulatedTime += timePassedInSeconds; //Save up the amount of time passed, incase we didn't get enough to fire anything.
     
     int bulletsToFire = (accumulatedTime / FIRE_DELAY); //Get the amount of bullets that we can fire, given the amount of time passed.
     accumulatedTime = fmod(accumulatedTime, FIRE_DELAY); //'Use up' the time that we are spending here.
     
     if(holdingSpacebarDown)
     {
        //Fire the bullets.
        for(bulletsToFire)
        {
            FireBullet();
        }
     }

     bulletsToFire = 0;
}

Basically, you want your keypresses and other events to change your game's logic state. Then, every update, you use your game's logic state, with the amount of time passed, to change your game's actual state.

Likewise, you have your enemy AI 'think' every so often, which changes their logic state, but then every update frame you use their logic state to affect their actual state based on the amount of time passed.

 

Drawing happens every frame (60 times a second or more). Events happen every so often depending on the user. AI thinking doesn't need to occur except maybe 5 or so times a second (depending on your game's needs). Game updating based on time and logic state doesn't need to occur except twenty or thirty times a second.

Edited by Servant of the Lord

Share this post


Link to post
Share on other sites

You don't really want "fire every time the key is pretended to be pressed by the operating system", what you really want is "fire every N millaseconds that the key is held down for".

 

So when SDL tells you, 'Spacebar was pressed', you mark 'bool spacebarIsHeld = true', and when they say 'Spacebar was released', you say, 'spacebarIsHeld = false'. (Or you can check the current state directly)

 

 

 

I did it! I already had my own function that returned 1 for key is down, 0 for key is being released and -1 for key is not being used. What I did, I just put a variable in the beginning of my update function:

frameStart = SDL_GetTicks();

Then I had my function update it using a variable to hold the current frame time and compare it with my delay:

if(GetKeyboardInput(SDL_SCANCODE_SPACE, event) == 1)
{
	frameTime += frameStart;
	if(frameTime >= fireDelay)
	{
		missiles.push_back(new Missile());
		missiles.back()->load("misslie", (position.GetX() + srcRect.w / 2), position.GetY(), renderer);
		frameTime -= fireDelay; 		
	}
}

Thanks a lot mate! biggrin.pngwub.png

Edited by lvenonl

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!