An incomplete Snake implementation using a Raspberry Pi 3, an adafruit st7735 screen and Python
:)
import time | |
import random | |
import digitalio | |
import board | |
import busio | |
from adafruit_rgb_display import rgb, st7735 | |
import RPi.GPIO as GPIO | |
from PIL import Image, ImageFont, ImageDraw | |
# NES colors :) | |
# colors are in BGR (not RGB) | |
colors = [ | |
rgb.color565(252, 0, 0), | |
rgb.color565(188, 0, 0), | |
rgb.color565(188, 40, 68), | |
rgb.color565(132, 0, 148), | |
rgb.color565(32, 0, 168), | |
rgb.color565(0, 16, 168), | |
rgb.color565(0, 20, 136), | |
rgb.color565(0, 48, 80), | |
rgb.color565(0, 120, 0), | |
rgb.color565(0, 104, 0), | |
rgb.color565(0, 88, 0), | |
rgb.color565(88, 64, 0), | |
rgb.color565(248, 120, 0), | |
rgb.color565(248, 88, 0), | |
rgb.color565(252, 68, 104), | |
rgb.color565(204, 0, 216), | |
rgb.color565(88, 0, 228), | |
rgb.color565(0, 56, 248), | |
rgb.color565(16, 92, 228), | |
rgb.color565(0, 124, 172), | |
rgb.color565(0, 184, 0), | |
rgb.color565(0, 168, 0), | |
rgb.color565(68, 168, 0), | |
rgb.color565(136, 136, 0), | |
rgb.color565(248, 248, 248), | |
rgb.color565(252, 188, 60), | |
rgb.color565(252, 136, 104), | |
rgb.color565(248, 120, 152), | |
rgb.color565(248, 120, 248), | |
rgb.color565(152, 88, 248), | |
rgb.color565(88, 120, 248), | |
rgb.color565(68, 160, 252), | |
rgb.color565(0, 184, 248), | |
rgb.color565(24, 248, 184), | |
rgb.color565(84, 216, 88), | |
rgb.color565(152, 248, 88), | |
rgb.color565(216, 232, 0), | |
rgb.color565(120, 120, 120), | |
rgb.color565(252, 252, 252), | |
rgb.color565(252, 228, 164), | |
rgb.color565(248, 184, 184), | |
rgb.color565(248, 184, 216), | |
rgb.color565(248, 184, 248), | |
rgb.color565(192, 164, 248), | |
rgb.color565(176, 208, 240), | |
rgb.color565(168, 224, 252), | |
rgb.color565(120, 216, 248), | |
rgb.color565(120, 248, 216), | |
rgb.color565(184, 248, 184), | |
rgb.color565(216, 248, 184), | |
rgb.color565(252, 252, 0), | |
rgb.color565(216, 216, 216) | |
] | |
def rand_col(): | |
return random.choice(colors) | |
class Dot: | |
def __init__(self, x, y, color): | |
self.x = x | |
self.y = y | |
self.color = color | |
def __repr__(self): | |
return "({},{},{})".format(self.x, self.y, self.color) | |
def rand_apple(width, height, dot_size, snake_body): | |
apple = Dot(random.randrange(0, width, dot_size), random.randrange(0, height, dot_size), rand_col()) | |
# checks that the apple is not in a position overlapping with the snake's body | |
for dot in snake_body: | |
if (dot.x == apple.x and dot.y == apple.y): | |
return rand_apple(width, height, dot_size, snake_body) | |
return apple | |
def draw_score_image(score, width): | |
image = Image.new('RGB', (width, 10), color = 'red') | |
draw = ImageDraw.Draw(image) | |
font = ImageFont.truetype("FreeMono.ttf", 10) | |
draw.text((10, 0), "score: {}".format(score), font=font) | |
return image | |
cs_pin = digitalio.DigitalInOut(board.CE0) | |
dc_pin = digitalio.DigitalInOut(board.D25) | |
reset_pin = digitalio.DigitalInOut(board.D24) | |
btn_right = digitalio.DigitalInOut(board.D17) | |
btn_right.direction = digitalio.Direction.INPUT | |
btn_left = digitalio.DigitalInOut(board.D22) | |
btn_left.direction = digitalio.Direction.INPUT | |
btn_up = digitalio.DigitalInOut(board.D27) | |
btn_up.direction = digitalio.Direction.INPUT | |
btn_down = digitalio.DigitalInOut(board.D23) | |
btn_down.direction = digitalio.Direction.INPUT | |
BAUDRATE = 24000000 | |
spi = board.SPI() | |
disp = st7735.ST7735R( | |
spi, | |
rotation=90, | |
cs=cs_pin, | |
dc=dc_pin, | |
rst=reset_pin, | |
baudrate=BAUDRATE, | |
) | |
height = disp.height | |
width = disp.width | |
border_size = 10 | |
dot_size = 10 | |
background_color = rgb.color565(0, 0, 0) | |
border_color = rgb.color565(100,100,100) | |
step = 10 | |
score_per_apple = 10 | |
body = [Dot(0, 30, rand_col()), Dot(0, 20, rand_col()), Dot(0, 10, rand_col()), Dot(0, 0, rand_col())] | |
apple = rand_apple(width - (border_size*3), height - (border_size*3), dot_size, body) | |
disp.fill_rectangle(0, 0, width, height, border_color) | |
disp.fill_rectangle(border_size, border_size, width - (border_size*2), height - (border_size*2), background_color) | |
score = 0 | |
score_image = draw_score_image(score, width) | |
while True: | |
head_x = body[0].x | |
head_y = body[0].y | |
new_head_x = head_x | |
new_head_y = head_y | |
if btn_up.value: | |
new_head_y = min(max(0, head_y - step), height - (border_size*3)) | |
if btn_right.value: | |
new_head_x = min(max(0, head_x + step), width - (border_size*3)) | |
if btn_down.value: | |
new_head_y = min(max(0, head_y + step), height - (border_size*3)) | |
if btn_left.value: | |
new_head_x = min(max(0, head_x - step), width - (border_size*3)) | |
if (new_head_x != head_x or new_head_y != head_y ): | |
if new_head_x == apple.x and new_head_y == apple.y: | |
# eat an apple | |
score = score + score_per_apple | |
score_image = draw_score_image(score, width) | |
body.insert(0, Dot(new_head_x, new_head_y, apple.color)) | |
apple = rand_apple(width - (border_size*3), height - (border_size*3), dot_size, body) | |
else: | |
# shifts all colors | |
head_color = body[0].color | |
for i in range(0, len(body) - 1): | |
body[i].color = body[i+1].color | |
removed_dot = body.pop() | |
body.insert(0, Dot(new_head_x, new_head_y, head_color)) | |
# clean up removed body dot | |
disp.fill_rectangle(border_size + removed_dot.x, border_size + removed_dot.y, dot_size, dot_size, background_color) | |
for dot in body: | |
disp.fill_rectangle(border_size + dot.x, border_size + dot.y, dot_size, dot_size, dot.color) | |
disp.fill_rectangle(border_size + apple.x, border_size + apple.y, dot_size, dot_size, apple.color) | |
disp.image(score_image, rotation=0) | |
time.sleep(1/60) |