Search code examples
c#xnadelaymonogame

Cooldown Ability in MonoGame


I have an ability for the player. I only want the player to be able to use this ability once every 5 seconds. I can always put this in my game loop:

Update(GameTime gameTime)
{
    GamePadState controller = GamePad.GetState(PlayerIndex.One);
    cooldown--;
    if(cooldown <= 0 && controller.Buttons.A == ButtonState.Pressed)
    {
        UseAbility();
        cooldown = 5000;
    }
}

But I am looking for something that will be exactly 5 seconds (opposed to 5000 update()'s), and I would like something more elegant than this barbarian code. Any suggestions? Thanks!


Solution

  • You can use the GameTime variable. You could try something like this:

    float cooldowntime = 0;
    Update(GameTime gameTime)
    {
        GamePadState controller = GamePad.GetState(PlayerIndex.One);
    
        cooldowntime += gameTime.ElapsedGameTime.TotalMilliseconds; 
        //if you are using XNA 3.1 or earlier, use GameTime.ElapsedRealTime
    
        if(cooldowntime >= 5000 && controller.Buttons.A == ButtonState.Pressed)
        {
             UseAbility();
             cooldowntime = 0;
        }
    }
    

    Using this, every update method, the cooldowntime will get the elapsed gametime in milliseconds added to it (if you are using XNA 3.1, you can use ElapsedRealTime, which is the time in "real life" elapsed. This would be useful if you get under 60fps). Then if cooldowntime is greater that 5000ms (5 seconds), the ability will be enabled for one update method. If you wanted to be more precise than GameTime.ElapsedGameTime.TotalMilliseconds, you could use a Stopwatch or DateTime.Now, for example. HTH

    Note: If you get exactly 60fps per update, ElapsedGameTime should be perfectly accurate.

    EDIT: To reduce the lines used, try this:

    float cooldowntime = 0;
    Update(GameTime gameTime)
    {
        GamePadState controller = GamePad.GetState(PlayerIndex.One);
    
        cooldowntime = (cooldowntime >= 5000 && controller.Buttons.A == ButtonState.Pressed) ? 0 : cooldowntime + gameTime.ElapsedGameTime.TotalMilliseconds; 
        if (cooldowntime == 0) UseAbility(); 
        // we know to use the ability if cooldowntime = 0 since it will only equal zero
        // when cooldowntime >= 5000 and the button is pressed.
    }