Home » maths » manifolds » Snakes on a Manifold: Part 2

# Snakes on a Manifold: Part 2

Welcome back. Last time we implemented the main components of the game. This time we will implement the main game loop. The job of the loop is to: get keyboard input, update the game state, update the display.

We will now be using pygame, so you might want to check out a tutorial before proceeding, but I think the best way to learn is just to dive right in. You will however need to install pygame before running the code. If you haven’t already, you should download the code from last time too. Finally if you want to skip to playing with the code yourself, here it is.

The Code
Ok here it is.

```import pygame
import snake as sk
from pygame.locals import *

class Game(object):
def __init__(self, size, topology, speed=6):
pygame.init()
#Resolution in pixels.
self.screen_resolution =600
self.topology=topology
self.speed = speed #Controls how fast the snake moves.
self.screen = pygame.display.set_mode((self.screen_resolution,
self.screen_resolution))
pygame.display.set_caption('SNAKES ON A MANIFOLD!')

self.board = sk.Board(size, topology)
#Put the snake in the center.
self.snake = sk.Snake([size/2, size/2], self.board.opposite_direction,
self.board.get_next_coord)
#Number of grid cells.
self.size=size
#Width in pixels of a grid cell.
self.square_size=int(self.screen_resolution/self.size)
#Now we name some colors in RGB for ease of use.
self.black = (0,0,0)
self.red = (255,0,0)
self.green = (0,255,0)
self.blue=(0,0,255)
self.darkgrey=(40,40,40)

self.background_colour=self.black
self.boundary_colour=self.blue
self.snake_colour = self.green
self.apple_colour=self.red

#Initialises screen to background color.
self.screen.fill(self.background_colour)

#Then we draw the boundary cells.
self.draw_boundary()

#This command updates the changes we have made to the screen.
pygame.display.update()

#Main game loop.
self.main()

def main(self):
score=0
Quit=False
first=True
while True: # main game loop
#Displays score in window caption.
pygame.display.set_caption('Topology: '+self.board.topology+'  |  Score: '+ str(score))
#Gets keyboard input
direction=None
for event in pygame.event.get():
if event.type == QUIT:
#User has closed window.
Quit=True
break
if event.type==pygame.KEYDOWN:
#User has pressed key.
if event.key==K_q:
Quit=True
break
if event.key==K_UP:
direction='UP'
if event.key==K_DOWN:
direction='DOWN'
if event.key==K_LEFT:
direction='LEFT'
if event.key==K_RIGHT:
direction='RIGHT'
if Quit:
break
#To see if anything has happened, we check where the head is.
#Now we find out what, apart from the head, is in the grid cell.

#The snake has hit the boundary or part of itself.
Quit=True
break
#The snake has found an apple.
self.snake.grow()
x,y=self.board.generate_apple()
self.draw_apple(x,y)
score+=1

self.update_board()
if first:
#When the game starts, the snake stands still waiting
#for user input to start the game.
x,y=self.board.generate_apple()
first=False
self.draw_apple(x,y)
self.draw_snake()
pygame.display.update()
while True:
got_direction=False
for event in pygame.event.get():
if event.type == QUIT:
Quit=True
break
if event.type==pygame.KEYDOWN:
if event.key==K_q:
Quit=True
break
if event.key==K_UP:
direction='UP'
got_direction=True
break
if event.key==K_DOWN:
direction='DOWN'
got_direction=True
break
if event.key==K_LEFT:
direction='LEFT'
got_direction=True
break
if event.key==K_RIGHT:
direction='RIGHT'
got_direction=True
break
if Quit:
break
elif got_direction:
break
if Quit:
break

self.snake.move(direction)
self.draw_snake()
pygame.display.update()
#This pauses the game to slow it down, adjust to make faster/slower.
pygame.time.Clock().tick(self.speed)
#Waiting to quit after died.
Quit=False
restart=False
while True: # main game loop
#Gets keyboard input

for event in pygame.event.get():
if event.type == QUIT:
Quit=True
break
if event.type==pygame.KEYDOWN:
if event.key==K_q:
Quit=True
break
if event.key==K_r:
restart=True
break
if Quit:
break
if restart:
break
if restart:
G=Game(self.size, self.topology)
pygame.quit()

def draw_boundary(self):
#Draws any boundary grid cells.
for row in range(self.size):
for col in range(self.size):
if self.board.grid[row, col]==1:
y=row*self.square_size
x=col*self.square_size
rect=pygame.Rect(x,y, self.square_size, self.square_size)
pygame.draw.rect(self.screen,self.boundary_colour, rect)

def draw_snake(self):
#We add a snake colored square where the head has moved,
#and add a background colored square where the tail was.
old_tail_position=self.snake.segments[0].previous_position

top=old_tail_position[0]*self.square_size
left=old_tail_position[1]*self.square_size
background_rect=pygame.Rect(left,top, self.square_size, self.square_size)
pygame.draw.rect(self.screen, self.background_colour,background_rect)

snake_rect=pygame.Rect(left,top, self.square_size, self.square_size)
pygame.draw.rect(self.screen, self.snake_colour,snake_rect)

def draw_apple(self, x, y):
apple_rect=pygame.Rect(y*self.square_size,x*self.square_size,
self.square_size, self.square_size)
pygame.draw.rect(self.screen, self.apple_colour, apple_rect)

def update_board(self):
#Updates the numpy array of the board.
old_tail_position = self.snake.segments[0].previous_position
```G=Game(20, 'Mobius Strip')