You're probably familiar with the game Space Invaders, which was originally made popular in the 1970s on the Atari (the first home gaming system). When it first came out, this game was pretty revolutionary. In fact, several of us here at RaspberrySTEM admit to spending many dozens (hundreds?) of hours sitting in front of our TV sets playing that game.
Over the next 10 projects, we're going to build a basic version of Space Invaders using the RaspberrySTEM components we've already wired up. The LED Matrix will be used to display the graphics, the accelerometer will be used to control the left and right movement of the ship (by tilting the Raspberry STEM left or right) and the button will be used to fire missiles at the invading aliens. As you can imagine, building this on an 8x8 LED Matrix display isn't going to allow us to create the awesome graphics you might be accustomed to in today's video game, but by the time we've completed this project, you should have all the basic skills necessary to build more complex games on other types of digital displays.
Like most games you'll build, this one is going to start with a game loop, and in this first Space Invaders project, we'll start by writing the pseudo-code for our game loop (see GAME LOOPS for more information on both pseudo-code and game loops). In our experience, the best way to write pseudo-code is in an iterative process, meaning that we write the very high level steps out first, and then we break each of those steps into smaller chunks with more details. We continue doing this until we have enough detail that we're ready to actually start writing our code.
Let's start with the basic outline for any game loop, much as we described in GAME LOOPS:
Initialize the game environment
while
(game not finished):
Check for user input
Update the game world
Draw graphics on the screen
Wait for some period of time
Finish & Cleanup
Now, let's look at each of these areas individually...
This
is where we're going to initialize all of the components and game
elements that we'll be using throughout our game. In our
Space
Invaders implementation, the three major components we'll have are the
ship that we control ("spaceship"), the alien ships that we try to
destroy ("aliens") and the missiles that we fire from our spaceship at
the aliens ("missiles"). We'll need to initialize the design,
position and other aspects of each of those components, as well as
general setup stuff, like importing the functions we'll need and
initializing the framebuffer.
Here's a general overview of what this part of the code will look like:
# Initialize the game environment
Import required functions/modules
Initialize framebuffer
Initialize accelerometer
Initialize spaceship
Initialize aliens
Initialize missiles
There will be other details that we'll add in there as well, but these are the big items we'll need to address in our intialization code.
This will be the start of our game loop. For this game, we'll loop continuously until the game is completed (either you destroy all the aliens or they get to the bottom of the screen and destroy you), at which point we can break from our while loop.
So, our loop will just be:
while True:
Unlike our previous game loops, for this game we'll be taking user input. Specifically, we'll be reading data from the accelerometer to know which direction the game is being tilted and we'll be checking the button to determine if a missile was fired. This part of the code will look something like:
# Check for user input
Get accelerometer input
Get button input
Each time through the loop, we'll have to update the status of all the three major components of the game -- the spaceship, the aliens and the missiles. In addition, we'll want to test to see any of the previously launched missiles has collided with an alien.
With that in mind this section of the code will look something like:
# Update the game world
Update the location of the spaceship
Update the location of the aliens
Update the location of any missiles
Check for any missile collisions
# Draw graphics on the screen
Erase the framebuffer
Draw the spaceship
Draw the aliens
Draw any missiles
Show the framebuffer
At the end of our game loop, we need to include a pause before continuing our next round through the loop. For this game, our graphics aren't going to (necessarily) update each time through the loop, so our wait time doesn't need to be correlated to our graphics updates. That said, we need to pick a time that is not too long -- otherwise the graphics will be as responsive as we'd like -- and also not too short -- or we risk overworking the processor.
We'll play around with various wait times and see what works, but typically, we'd expect something in the .001 to .1 seconds time frame...
# Wait for some period of time
Wait for between .001 and .01 seconds
Finally, we need to handle the case where we fall through the loop, either because we've won the game (destroyed all the aliens) or lost the game (the aliens got to the bottom of the screen). In either case, we'll at least print the final game status (win or lose) to the output window.
# Finish & Cleanup
Print "You won!" if the player wins
Print "You lost..." if the player loses
Here is what the full pseduo-code for this game will look like...we'll spend the next 8 projects building it piece-by-piece:
# Initialize the game environment
Import required functions/modules
Initialize framebuffer
Initialize accelerometer
Initialize spaceship
Initialize aliens
Initialize missiles
while True:
# Check for user input
Get accelerometer input
Get button input
# Update the game world
Update the location of the spaceship
Update the location of the aliens
Update the location of any missiles
Check for any missile collisions
# Draw graphics on the screen
Erase the framebuffer
Draw the spaceship
Draw the aliens
Draw any missiles
Show the framebuffer
# Wait for some period of time
Wait for between .001 and .01 seconds
# Finish & Cleanup
Print "You won!" if the player wins
Print "You lost..." if the player loses