ProjectCaseStudy SnakeGame
ProjectCaseStudy SnakeGame
Description:
This project creates the Snake Game seen in the Worked Example for the 9/10 MOOC, using a Makey
Makey controller to build skill in the use of digital systems, Object-Oriented programming design and
implementation, and data representation. Students will learn about Object-Oriented programming using
existing Classes and Objects, as well in designing and creating multiple new Classes, making this a good
intermediate project.
Resources:
● MakeyMakey kit
● Mac or PC with Python 3 and pygame library installed
● Free USB port to plug MakeyMakey into
Defining the To create a Snake game that allows users to control the movement of a
Problem snake on a screen, to get points for eating food and avoiding running into the
walls or the growing tail of the snake itself.
Our system is going to involve working with both hardware and software, and
so we will need to understand what we have available in hardware that can
assist us.
Now that understand how our hardware will work in the design of our system,
let’s move on to starting the design of our software system.
We have to think about the Classes that we want to build, with the associated
variables and functions that will make sense for the development.
Let's start by looking at the snake itself, the hero of the game. The snake has
a location on the screen, and contains multiple visual elements, as it can
grow, and the snake's head is connected to the rest of the snake and the
snake's body follows it around the screen. If the snake "eats" food, it grows.
The snake also keeps track of which way it’s going, using the heading
variable. This gives us a high level Class design of:
Here are the requirements (functional requirements) for how the snake moves.
The snake moves in a very precise way. Based on what the user types, the
snake will move in a given direction. Every time the snake moves, the head
will go in the new direction, and every piece of the snake will move up, by
occupying the space that was formerly occupied by the piece in front of it.
To grow in size, the snake has to eat food. How can we show the snake
eating? The simplest answer is that if the head of the snake and the food are
in the same place, we consider that the snake eats the food. This means that
we have to know where the food is. When it’s eaten, it disappears, the snake
grows, and the food shows up somewhere else.
The coordinates of the food are part of its variables and it has a function
move, which will move it to a different place. To make the game interesting,
we probably want this to be a random location, which means that we'll have to
make sure that our program can generate random numbers. I also made a
note that the food will keep track of its own colour, that would be another
variable.
But we also wanted to show a score, so we need a variable to keep track of
that as well. In this case, we’ll create a Scoreboard class where we can
increase the counter value and display it.
Let's look at how a program to run the whole game might look:
1. Draw the playing area with bounding rectangle, set the counter to zero
and display it.
2. Draw the snake in a starting position.
3. Draw the food in a starting location.
4. On user input, change snake direction.
5. Move the snake one move
6. If the snake is over food, eat it, increase the score, grow, move the
food,
7. else if the snake is over itself or in a wall, die.
8. Go back to 4.
9. Until the snake dies
We didn’t talk about what makes the snake die. The snake eats when the food
and the snake’s head are in the same place. In a game, we refer to that as
collision detection. Although the objects didn’t really collide, in a real world
sense, they are in the same place and we can perform actions based on this.
We’re going to use collision detection to see when the snake runs into its own
body, which means that we’re going to have to keep track of every piece of
the body in variables in our program. Just because something is drawn on the
screen doesn’t mean that it’s still stored in a variable somewhere.
Understanding our Most of the data representation in the program is straightforward. The score is
Data a number. The position of the food is given by an (x,y) coordinate pair but the
food’s move function needs to know the size of the canvas if it’s going to
randomly appear in a place where we can eat it.
Our Scoreboard class needs to be told when the score has increased and this
function will be called whenever the snake runs over food.
The Snake is more complex as it needs to know the bounds of the canvas, the
location of the food, and the location of all pieces of itself.
Thus, the Snake class keeps track of where the head of the Snake is but
stores a list of Body pieces. By providing a collide function in the Snake class,
the Snake objects can search their internal set of pieces to see if any of them
match the position of the head. The result of this search is returned to the
calling program.
The Snake’s eat method, which was not originally implemented in the Worked
Example, should take a food as a parameter and check to see if the food and
the Snake are in the same place. If they are, the Snake should grow, the
counter should increase, and the food should move.
Prototyping and Sketch prototypes are very useful to get a feel for how the game will work.
User Interface These can be actual sketches or small examples using a whiteboard or post-it
Design notes.
And here are the whiteboard examples, showing a snake moving, eating food,
and then growing after eating.
Because we are using the MakeyMakey, students are free to develop their
own control systems for the snake game. What will these look like?
Implementation The full Python3 code for this is shown below. This will automatically connect
to a MakeyMakey hooked in and using the directional arrows.
The MakeyMakey will need to be connected to the USB port and the earth
lead held by (or attached to) the person who’ll be playing the game. Each of
the directional controller leads will need to be attached and either touched
directly by the player or connected to another object that will act as the arrow.
bod2 = Body(x-40,y)
self.bodylist.append(bod2)
bod3 = Body(x-60,y)
self.bodylist.append(bod3)
def draw(self):
for element in self.bodylist:
pygame.draw.rect(main,(0,255,0),((element.x-10,element.y-10
),(20,20)),0)
pygame.draw.rect(main,(10,128,0),((self.x-10,self.y-10),(20
,20)),0)
def setheading(self,keystroke):
self.heading=keystroke
def collide(self):
for bd in self.bodylist:
if ((self.x,self.y)==(bd.x,bd.y)):
return True
return False
def grow(self):
tmpbody=self.bodylist[len(self.bodylist)-1]
self.bodylist.append(tmpbody)
def move(self):
self.bodylist.insert(0,Body(self.x,self.y))
removeBlock=self.bodylist.pop()
pygame.draw.rect(main,(255,255,255),((removeBlock.x-10,remo
veBlock.y-10),(20,20)),0)
if (self.heading==pygame.K_RIGHT):
self.x+=20
elif (self.heading==pygame.K_DOWN):
self.y+=20
elif (self.heading==pygame.K_UP):
self.y-=20
elif (self.heading==pygame.K_LEFT):
self.x-=20
elif (self.heading==pygame.K_q):
sys.exit()
else:
return
# The eat function checks to see if the head of
# the snake and the food are in the same place.
# If they are, return True, else False
def eat(self,food):
return ((food.x==self.x) and (food.y==self.y))
pygame.draw.rect(main,(255,255,255),((self.x-10,self.y-10),
(20,20)),0)
self.x=randint(1,34)*20
self.y=(randint(1,22)*20)+20
def increase(self):
self.score=self.score+1
# The display function redraws the black rectangle at the
# top because constant redrawing of the text makes it
# blurry. The text is a rendered string that contains the
# Score information. The blit function call sends the
# rendered text to the screen.
def display(self):
pygame.draw.rect(main, (0,0,0), ((0,0),(720,20)),0)
text=font.render("Score "+ str(self.score),
True,(255,0,0))
main.blit(text,(320,5))
def Main():
# Set up all of the objects
scoreboard = Scoreboard()
blueberry = Food()
snake = Snake(100,80)
if event.type == pygame.KEYDOWN:
snake.setheading(event.key)
pygame.time.delay(100)
if __name__ == '__main__':
pygame.display.set_caption("Snake Game")
pygame.draw.rect(main, (0,0,0), ((0,0),(720,20)),0)
pygame.draw.rect(main, (0,0,0), ((0,20),(720,460)), 16)
Main()
# And that's it!
Testing and How can we test a full Snake game and, assuming it passes that stage, how
Evaluation can we playtest that?
To display the snake, the first thing we want to do is to make sure that we can
draw the snake and move it around on the screen. So our testing for correct
function will be:
1. Can I display the snake's head on the screen?
2. Will it move around as I want it to using keyboard control?
3. Is it displaying correctly?
4. Is the body moving correctly?
If we identify an error in the snake, because it's a Class, we will go into the
Snake class and fix it there. However, because we've written the Food and
Scoreboard as separate classes, whatever we do in the Snake class shouldn't
break anything in there, unless we accidentally change the code without
noticing. The next step for the snake will be checking what happens when the
head is detected as colliding with something. Does it grow when it eats food?
Does it die when it hits a wall or itself? We'd then continue to test the program
until we've tested all of the individual elements and their interactions together.
One useful test case is to see if everything is being drawn where you expect.
Because we aren't using all the screen, it's possible to draw the food or the
snake so that it overlaps the black rectangle that's the boundary. Has the
programmer put the correct limits on the ranges where the snake and the food
can appear?
Testing the non-functional requirements often falls into the realm of playability.
We noted before that we can ask students whether the controls are obvious
and responsive, and whether the game is fun to play. But they may have to
play for a while to get a real feeling for it. What's it like to play the game for an
extended period?
Many snake games increase the speed of the snake as it gets longer,
increasing the difficulty even further. This increased movement speed gives a
sense of urgency and can be a way to engage players with the snake. But
make it too fast and it becomes unplayable!
Project Extensions There are many ways this could be extended. Some that we have thought of
include:
● How would students go about producing a two-player game?
● Can you make the Snake speed up as it gets longer?
● Can you use a timer to make the Snake starve if it doesn’t eat quickly
enough?
Project Reflection
In this project, students will undertake an extensive design and implementation process, combining
elements of hardware and software. The project is well suited to be taught over a number of sessions,
and using group work. While we have not included explicit assessment information here, we have
provided a discussion of how these sessions might be structured, and how students might be able to
demonstrate their learning.
For a more extensive discussion of assessment possibilities within Digital Technologies at this level,
please join us in our online community and course: www.csermoocs.adelaide.edu.au
Encourage students to help each other - and look for help on the internet.
Ask a friend. Ask Google. Then ask the teacher.
While students are working in groups, ask questions to give them the
opportunity to demonstrate their thinking and understanding:
Learning demo
What challenges have you faced in developing this design?
Learning reflection Remind students that this is a very simple game but that the program we
have been developing has a development process that you would find in
real-world game development. The steps that they have taken can be
applied to many other larger projects
● Can you think of any exciting games that they want to build, which
they haven’t managed to find anywhere else?
● How else could we control the Snake?
● Could we build a ‘brain’ for the Snake that plays the game for us?
What would that look like?
Further Resources:
1. Information about Python, including tutorials: http://python.org
2. Information on the pygame library: http://pygame.org
3. Information on the MakeyMakey: http://makeymakey.com/