Skip to content

Instantly share code, notes, and snippets.

@m1cr0lab
Last active July 2, 2019 16:17
Show Gist options
  • Save m1cr0lab/690f22fe8506ab7a2739dd6b40377b94 to your computer and use it in GitHub Desktop.
Save m1cr0lab/690f22fe8506ab7a2739dd6b40377b94 to your computer and use it in GitHub Desktop.
Learn to Code a Snake Game with CircuitPython on Gamebuino META
# ----------------------------------------------------------
# Learn to Code a Snake Game with Python
# Gamebuino Academy Workshop
# https://gamebuino.com/academy/workshop/learn-to-code-a-snake-game-with-python
# ----------------------------------------------------------
# This game is based on the CircuitPython environment, which
# is an implementation of the Python language specific to
# microcontrollers. CircuitPython runs on the SAMD21G18
# architecture of the Gamebuino META.
# ----------------------------------------------------------
# Author: Steph
# Date: April 2019
# ----------------------------------------------------------
from gamebuino_meta import waitForUpdate, display, color, buttons
from random import randint
# ----------------------------------------------------------
# Global variables
# ----------------------------------------------------------
SCREEN_WIDTH = 80
SCREEN_HEIGHT = 64
SNAKE_SIZE = 2
SNAKE_LENGTH = 4
SNAKE_EXTENT = 2
COLS = (SCREEN_WIDTH - 4) // SNAKE_SIZE
ROWS = (SCREEN_HEIGHT - 4) // SNAKE_SIZE
OX = (SCREEN_WIDTH - COLS * SNAKE_SIZE) // 2
OY = (SCREEN_HEIGHT - ROWS * SNAKE_SIZE) // 2
COLOR_BG = 0x69c0
COLOR_WALL = 0xed40
COLOR_SNAKE = 0xfd40
COLOR_APPLE = 0x07f0
COLOR_SCORE = 0xffff
COLOR_LOST_BG = 0x8800
COLOR_LOST_FG = 0xffff
MODE_START = 0
MODE_READY = 1
MODE_PLAY = 2
MODE_LOST = 3
# ----------------------------------------------------------
# Game management
# ----------------------------------------------------------
def tick():
if not game['refresh']:
clearSnakeTail()
if game['mode'] == MODE_START:
resetSnake()
spawnApple()
game['mode'] = MODE_READY
game['score'] = 0
game['time'] = 0
elif game['mode'] == MODE_READY:
game['refresh'] = False
handleButtons()
moveSnake()
if snakeHasMoved():
game['mode'] = MODE_PLAY
elif game['mode'] == MODE_PLAY:
handleButtons()
moveSnake()
if game['refresh']:
game['refresh'] = False
if didSnakeEatApple():
game['score'] += 1
game['refresh'] = True
extendSnakeTail()
spawnApple()
if didSnakeBiteItsTail() or didSnakeHitTheWall():
game['mode'] = MODE_LOST
game['refresh'] = True
else:
handleButtons()
draw()
game['time'] += 1
def spawnApple():
apple['x'] = randint(0, COLS - 1)
apple['y'] = randint(0, ROWS - 1)
def handleButtons():
if buttons.pressed(buttons.LEFT):
dirSnake(-1, 0)
elif buttons.pressed(buttons.RIGHT):
dirSnake(1, 0)
elif buttons.pressed(buttons.UP):
dirSnake(0, -1)
elif buttons.pressed(buttons.DOWN):
dirSnake(0, 1)
elif game['mode'] == MODE_LOST and buttons.pressed(buttons.A):
game['mode'] = MODE_START
# ----------------------------------------------------------
# Snake management
# ----------------------------------------------------------
def resetSnake():
x = COLS // 2
y = ROWS // 2
snake['x'] = []
snake['y'] = []
for _ in range(SNAKE_LENGTH):
snake['x'].append(x)
snake['y'].append(y)
snake['head'] = SNAKE_LENGTH - 1
snake['len'] = SNAKE_LENGTH
snake['vx'] = 0
snake['vy'] = 0
def dirSnake(dx, dy):
snake['vx'] = dx
snake['vy'] = dy
def moveSnake():
h = snake['head']
x = snake['x'][h]
y = snake['y'][h]
h = (h + 1) % snake['len']
snake['x'][h] = x + snake['vx']
snake['y'][h] = y + snake['vy']
snake['head'] = h
def snakeHasMoved():
return snake['vx'] or snake['vy']
def didSnakeEatApple():
h = snake['head']
return snake['x'][h] == apple['x'] and snake['y'][h] == apple['y']
def extendSnakeTail():
i = snake['head']
n = snake['len']
i = (i + 1) % n
x = snake['x'][i]
y = snake['y'][i]
for _ in range(SNAKE_EXTENT):
snake['x'].insert(i, x)
snake['y'].insert(i, y)
snake['len'] += SNAKE_EXTENT
def didSnakeBiteItsTail():
h = snake['head']
n = snake['len']
x = snake['x'][h]
y = snake['y'][h]
i = (h + 1) % n
for _ in range(n-1):
if snake['x'][i] == x and snake['y'][i] == y:
return True
i = (i + 1) % n
return False
def didSnakeHitTheWall():
h = snake['head']
x = snake['x'][h]
y = snake['y'][h]
return x < 0 or x == COLS or y < 0 or y == ROWS
# ----------------------------------------------------------
# Graphic display
# ----------------------------------------------------------
def draw():
if game['refresh']:
clearScreen()
drawWalls()
drawSnake()
else:
drawSnakeHead()
drawScore()
drawApple()
def clearScreen():
color = COLOR_LOST_BG if game['mode'] == MODE_LOST else COLOR_BG
display.clear(color)
def drawWalls():
color = COLOR_LOST_FG if game['mode'] == MODE_LOST else COLOR_WALL
display.setColor(color)
display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
def drawSnake():
isTimeToBlink = game['time'] % 4 < 2
color = COLOR_LOST_FG if game['mode'] == MODE_LOST and isTimeToBlink else COLOR_SNAKE
n = snake['len']
for i in range(n):
drawDot(snake['x'][i], snake['y'][i], color)
def drawSnakeHead():
h = snake['head']
drawDot(snake['x'][h], snake['y'][h], COLOR_SNAKE)
def clearSnakeTail():
h = snake['head']
n = snake['len']
t = (h + 1) % n
drawDot(snake['x'][t], snake['y'][t], COLOR_BG)
def drawScore():
display.setColor(COLOR_SCORE)
display.print(2, 2, game['score'])
def drawApple():
drawDot(apple['x'], apple['y'], COLOR_APPLE)
def drawDot(x, y, color):
display.setColor(color)
display.fillRect(OX + x * SNAKE_SIZE, OY + y * SNAKE_SIZE, SNAKE_SIZE, SNAKE_SIZE)
# ----------------------------------------------------------
# Initialization
# ----------------------------------------------------------
game = {
'mode': MODE_START,
'score': 0,
'time': 0,
'refresh': True
}
snake = {
'x': [],
'y': [],
'head': 0,
'len': 0,
'vx': 0,
'vy': 0
}
apple = { 'x': 0, 'y': 0 }
# ----------------------------------------------------------
# Main loop
# ----------------------------------------------------------
while True:
waitForUpdate()
tick()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment