Advertisement

SDL Pausing game help?

Started by November 26, 2014 05:43 PM
10 comments, last by rip-off 10 years, 1 month ago

No worries. It is easy to over-think some of these things sometimes.

Yeah, I got it working, feel free to close this post so no more responses get posted here :)

Great.

Note we don't generally close posts. If a post is descending into a hostile environment, we close it, and if someone resurrects an old post we also close them.

Even at this point, someone could come along with another way to handle this.

As an example, one way I've handled this in the past for small to medium games is to treat the game as a series of "states". So you might have a MainMenuState, a PlayingState, a PausedState, among others.

So we might have something like:

class GameState
{
public:
    virtual ~GameState();
 
    virtual void update() = 0;
 
    virtual void display(Renderer &) = 0;
 
    virtual void handleEvent(const SDL_Event &event) = 0;
 
    virtual std::unique_ptr<GameState> nextState() = 0;
 
    // ...
};

So you could imagine for a basic game like Pong, you might have a PlayingGameState that looks something like this:

class PlayingPongState : GameState
{
public:
    virtual void update()
    {
        ball.update();
 
        leftPaddle.update();
        rightPaddle.update();
 
        handleCollision(ball, leftPaddle);
        handleCollision(ball, rightPaddle);
       
        checkForPoint(ball);
 
        // ...
    }
 
    virtual void display(Renderer &renderer)
    {
        renderer.drawCircle(ball.position, ball.radius);
        renderer.drawRect(leftPaddle.position, leftPaddle.dimensions);
        renderer.drawRect(rightPaddle.position, rightPaddle.dimensions);
    }
 
    virtual void handleEvent(const SDL_Event &event)
    {
        if (event.type == SDL_KEYDOWN)
        {
            if (event.key.keysym.sym == SDLK_UP)
            {
                rightPaddle.startMovingUp();
            }
            else if (event.key.keysym.sym == SDLK_DOWN)
            {
                rightPaddle.startMovingDOWN();
            }
            else if (event.key.keysym.sym == SDLK_W)
            {
                leftPaddle.startMovingUp();
            }
            else if (event.key.keysym.sym == SDLK_S)
            {
                leftPaddle.startMovingUp();
            }
        }
    }
};

Then in your top level loop, you have something like this:

bool running = true;
std::unique_ptr<GameState> currentState(new PlayingPongState());
while (running)
{
     SDL_Event event;
     while (SDL_PollEvent(&event))
     {
          if (event.key == SDL_QUIT)
          {
              running = false;
          }
          else
          {
              currentState->handleEvent(event);
          }
     }
 
     currentState->update();
     currentState->display(renderer);
     // ...
 
     // Forgive me if this won't compile, I've not used C++11 much.
     std::unique_ptr<GameState> nextState = currentState->nextState();
     if (nextState)
     {
         std::swap(currentState, nextState);
     }
}

So for pausing, you might handle this with a fake state that continues to display the gamestate, but avoids updating it:

class PausedState : GameState
{
public:
    PausedPongState(std::unique_ptr<GameState> underlyingState)
    :
           returnToGame(false),
           underlyingState(underlyingState)
    {
    }
 
    virtual void update()
    {
        // Nothing to do here.
    }
 
    virtual void display(Renderer &renderer)
    {
        underlyingState->display(renderer);
        renderer.displayText("Paused", renderer.screenCentre());
    }
 
    virtual void handleEvent(const SDL_Event &event)
    {
        if (event.type == SDL_KEYDOWN)
        {
            if (event.key.keysym.sym == SDLK_RETURN)
            {
                returnToGame = true;
            }
        }
    }
 
    virtual std::unique_ptr<GameState> nextState()
    {
          // Ditto on C++11
          std::unique_ptr<GameState> result;
          if (returnToGame)
          {
              std::swap(result, underlyingState);
          }
          return result;
    }
 
private:
    bool returnToGame;
    std::unique_ptr<GameState> underlyingState;
};

And add some code to pause to the event loop:

while (SDL_PollEvent(&event))
{
    if (event.type == SDL_QUIT)
    {
        running = false;
    }
    else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_p)
    {
        // Not sure this is totally necessary...
        std::unique_ptr<GameState> temp;
        std::swap(currentState, temp);
        std::unique_ptr<GameState> pausedState(new PausedState(std::move(temp)));
        std::swap(pausedState, currentState);
    }
    else
    {
        currentState->handleEvent(event);
    }
}

I'm not saying this is the best solution by any means, but it is an alternative to scattering a bunch of if() checks around.

This topic is closed to new replies.

Advertisement