Search code examples
c#xna

How to create a pause like effect while counting down in XNA


I'm creating a simple game, where whenever I leave the menu I want a 3 second timer to cover up the screen, while the game is paused. I had imagined I would do something like this

protected void Draw(GameTime gameTime)
{
    //..//
    for(int i = 3; i > 0; i--)
    {
        spriteBatch(gameFont, i.ToString(), new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);
        Thread.Sleep(1000);
    }
    //..//
}

However, this just pauses at the menu for three seconds, then immediatly puts you in game. You can for a split second see a random number, but not at all a real countdown. What can I do to pause the games running and still draw the game?


Solution

  •    Thread.Sleep(1000);
    

    At the best of times you want to avoid using Thread.Sleep() and I can't think of any-time you should use it in a game. Games should be running flat-out and you want to minimise situations where the CPU is blocking or just sleeping.

    What can I do to pause the games running and still draw the game?

    Generally in games (and XNA is no exception), the draw code is separate from state update mechanics. This means your Draw() should be focused on drawing and nothing else.

    Pausing can be considered a game state and is better served being processed in your game's Update().

    Consider adding a state to your game, perhaps:

    enum States
    {
        Initialising,
        InMenu,
        LeavingMenu,
        InGame,
    }
    
    States _state;
    

    Then in your Update() you could work on your state machine, switching from in-menu; to leaving menu; to finally in game:

    DateTime timeOfEscPressed;
    protected virtual void Update(GameTime gameTime)
    {
        switch (_state)
        {
            case States.Initialising:
                break;
            case States.InMenu:
                // *** pseudo-code here ***
                // if ESC pressed then 
                //    _state = States.LeavingMenu
                //    timeOfEscPressed = DateTime.Now;
                break;
    
            case States.LeavingMenu:
                // stay in this state for 3 seconds
                if ((DateTime.Now - timeOfEscPressed).TotalSeconds >= 3)
                {
                    _state = States.InGame;
                }
                break;
    
            case States.InGame:
                if (menuKeyPressed) // pseudo code
                {
                    _state = States.InMenu;
                    timeOfEscPressed = DateTime.Now;
                }
                break;
        }
    }
    

    Your draw code becomes just that, draw code:

    protected void Draw(GameTime gameTime)
    {
        switch (_state)
        {
            case States.InMenu:
                DrawMenu();
                break;
            case States.LeavingMenu:
                ShowTimer();
                break;
        }
    }
    

    In this way, you gain the illusion of your game pausing but without freezing the update-draw loop.