1. Introduction
  2. Graphics
  3. Physics
  4. Collision Detection
  5. Computer AI
  6. Screen Transitions (You’re here!)
  7. Postmortem

Whoa! It’s been a while since the last time I talked about Pocket League! To be fair, I’ve been busy and haven’t done any of the work on the sound effects that I thought I would have completed by now.

Let’s talk about something a bit simpler then: how Pocket League handles screen transitions.


Stitching a Game Together

To date, we’ve covered a lot of things (see above in Other Posts In This Series). We have graphics, physics, collision detection, and AI. What we need now is to string it all together into a functional game!

Let’s take a look at all the screens the game has and how they’re linked together:

Pocket League Diagram

Starting from the top, working counterclockwise:

  • The main menu (duh)
    • Gameplay, where most of the topics from this blog post live
      • Win screen :)
      • Lose screen :(
    • Credits

You’ll notice every path loops back to the main menu at some point.


Under the Hood

Implementation of this functionality is actually VERY simple. It’s essentially a state machine. First, we define an enum with all the possible screen types, of which there are 5.

typedef enum {
    TITLE,
    GAME,
    CREDITS,
    PLAYER_WINS,
    CPU_WINS
} screen_t;

The game uses a function for each screen type. For the title screen or main menu, there’s a title() function, just like there’s a game(), and credits() function. For the endgame screen, there’s a single game_end() function that takes the current screen type to determine which player wins. So: game_end(PLAYER_WINS) would execute the code for the win screen, just like game_end(CPU_WINS) would run code for the loss screen.

The main() function is the entry point to the game, and it simply operates a while loop that tracks the current screen and executes the appropriate screen function:

void main() {
  // Sets up the palette registers for proper display
  BGP_REG = OBP0_REG = OBP1_REG = 0xE4;

  // Define the sprite size
  SPRITES_8x8;

  // Current screen, defaults to TITLE
  screen_t current_screen = TITLE;

  while(1) {
    if (current_screen == TITLE) {
      current_screen = title();
    }
    else if (current_screen == GAME) {
      current_screen = game();
    }
    else if (current_screen == CREDITS) {
      current_screen = credits();
    }
    else if (current_screen == PLAYER_WINS || current_screen == CPU_WINS) {
      current_screen = game_end(current_screen);
    }
  }
}

And that’s it! It’s really a simple system. Each one of these functions has a screen_t return value, so a “screen transition” is just a function return in the main() function that executes the next screen function.

Each screen is free to work however it needs to as long as it eventually returns the next screen type (otherwise, the game would hang!). For instance, as we’ve seen before, the game loop operates a very complicated while loop that only returns when either the player or computer scores 5 goals. On the other hand, the credits screen simply waits for the player to press Start before returning.


Hope you’re continuing to enjoy this series – I’m getting close to wrapping it up. All that’s left is to finish the sound effects for the game and clean up / refactor some of the messy code before I release v1.0 of Pocket League! Of course, there’ll be a blog post about that as well.

Thanks for reading.