CS/ENGR
101: Gameboy Session
Fall 2006 – Snake Game Project (Days
7-9)
Due: Wednesday, November 29
Snake Game
The Snake Game is an old video game which has become a standard cellphone game. In this game, a snake moves around a screen and is controlled by the player using a joystick or arrow keys. The object of the game is to collect points by guiding the snake to eat apples (or other desirable objects) and to avoid running into walls and the snake body, which causes to game to end. In some versions, the snake is of fixed length. In other versions, the snake grows as the game is played. Below is a picture of a version that grows†:

Gameboy Snake
For this project, you will write a program that will allow a user to play a simplified Snake Game on the Gameboy. Our version will have the following features:
The snake body will grow as the game is played.
The snake body will consist of one line of pixels.
There will not be any apples, only walls.
The score will be the number of pixels long the snake is before a wall or the snake body is hit.
To make the game more "real", it will start with a text splash screen and wait for the player to press the START button (more on this below)
Also to be more "real", a text screen will display the final score and wait for the player to press the A button to play again.
To make this program easier to understand, we will break it up into several functions. We will use the ClearScreen function from previous exercises. Here are descriptions of the other functions.
PeekPixel
The first new function you will need is one to find out the color of a pixel. This is basically the opposite of ham_PutPixel, but for some reason the GBA library doesn't implement one, so we have to do it ourselves. The code for this function is below. (Don't worry about understanding how it works.)
/* returns the color of the pixel at (x, y)*/
int PeekPixel (int x, int y)
{
return *(MEM_VRAM_PTR + 240 * y + x);
}
DisplayStartScreen
Another function we need is one to make the text splash screen. It requires that we change to text mode rather than graphics mode. In this mode, the screen is divided into characters rather than pixels. Since each character is 8x8 pixels, the screen has 30x20 characters. In this mode, only letters, digits, and (most of) the English text punctuation marks (e.g., '!', but not "*") will display and the letters are displayed capitalized (even when they are in lowercase in the output string). The code for this function is below.
void DisplayStartScreen ()
{
ham_SetBgMode (0); /* 0 is text mode */
ham_InitText(0); /* Required initialization */
/* ham_DrawText arguments are (x,y) of where to
place text, and the text */
ham_DrawText (5, 2, "Welcome to Snake");
ham_DrawText (5, 4, "Press START to begin");
while (!F_CTRLINPUT_START_PRESSED); /* spin until START is pressed */
ham_DeInitText(); /* Required deinitialization */
}
DisplayFinalScore
You will need to write a similar function DisplayFinalScore that has an argument that is the score to be displayed for the final score reporting text screen. This function also should wait for the player to press the A button to start a new game. Here is a skeleton of its function definition:
void DisplayFinalScore (int score)
{
/* code for this function goes here
}
PlayGame
The final function we will write is PlayGame, which holds the main game code. We put the game code in a separate function from the main program code to make it easier to change between the text mode of the splash and score screens and the graphics mode of the game screen. This function will return the final score the player earned. Here is a skeleton of its function definition:
int PlayGame ()
{
/* code for this function goes here */
}
The main idea of this program is that the snake will be growing continuously (whether or not the user presses a button). The arrow buttons will control the direction that the snake is growing. We will do this by encoding the direction as an integer. For example, we can use 0 for left, 1 for right, 2 for up, and 3 for down.
The program will determine if the snake has hit anything by finding out the color of the pixel it advances to, and testing to see if it is the background color. If the pixel is the background color, the space is free and the snake grows by coloring that pixel. If it is not the background color, then either it is a wall or the body of the snake itself. In this case, the game ends and reports the player's score. Here is an outline of what the PlayGame function should do:
Declare all needed variables
Set the background mode to 3
Initialize x and y to be the coordinates of the pixel in the center of the screen
Initialize score to 0 and direction to 0 (i.e., up will be the initial direction)
Clear the screen to background color using the ClearScreen function.
Draw a border around the edge of the screen in a different color By making the border a different color than the background, the edge of the screen becomes a wall, and the game will automatically stop when the snake hits the edge. This way, we will not need to check for the edge as was needed for the Etch-a-Sketch® project.
In a while (TRUE) loop, do the following tests and actions
Check if direction is 0 (left), if so update x so that (x, y) is now one pixel to the left
Check if direction is 1 (right), if so update x so that (x, y) is now one pixel to the right
Check if direction is 2 (up), if so update y so that (x, y) is now one pixel higher
Check if direction is 3 (down), if so update y so that (x, y) is now one pixel lower
Check if color at (x,y) is not the background color (using the PeekPixel function), if so do something to attract the player's attention like flashing the screen red and return the score (this will terminate the function and thus end the game)
Color the pixel at coordinates (x, y) the snake color (since it is at a free pixel)
Increment the score by 1 (since a pixel was added to the snake)
Check if the Left button has been pressed, if so set direction to 0
Check if the Right button has been pressed, if so set direction to 1
Check if the Up button has been pressed, if so set direction to 2
Check if the Down button has been pressed, if so set direction to 3
Delay for some amount of time (otherwise, the snake will be drawn too rapidly to control)
Note that this outline is both similar to and different from the Etch-a-Sketch® project outline.
Main Program
The main program then is just a loop that alternates between the start splash screen, playing the game, and the final score screen as follows.
int main(void)
{
int finalScore; /* holds the final score from playing the game */
ham_Init();
while(TRUE)
{
DisplayStartScreen ();
finalScore = PlayGame();
DisplayFinalScore (finalScore);
}
return 0;
}
Logistics
Create a new VisualHAM project for this assignment. Recall that after launching VH, the steps for doing this are:
Click on the File menu and choose New, then Project. This gives you the dialog box to create one.
In the new project dialog box, select [C] Empty, type in a project name (for example, snake), and give a place on your network drive space for a location (this needs to be specified using a drive letter, for example, I:\cs101\snake assuming you have a folder named cs101 on your network drive).
In the left panel, there is a tree representation of the project. The code you write goes in the main.c file. Double-clicking on the entry will bring up the file in the main edit window.
All of the function definitions need to go before the main program code.
Assignment
This assignment is worth 60 points. They will be awarded as follows:
50 points – Writing a program that meets the basic Gameboy snake program outlined above.
10 points – Place some interior "walls" in the playing field to make the game more interesting.
10 points extra credit - Make the game go faster the longer the game is played by reducing the delay at various intervals. For example, every 100 points the delay gets 10% shorter.
Put your name in a comment at the beginning of your program file. Email your completed program (the main.c file, not the project file) as an attachment to the instructor (hwang@evansville.edu) no later than 4:30pm on Wednesday, November 29.
†From Feed the Snake Game by Real Apex http://www.feedthesnake.com
11/17/06