Files @ 835bac5d3b3c
Branch filter:

Location: led-matrix-software/demos/snake.py

matthewreed
Added new demos and handle splash screens and controller input
### snake.py
### Author: Matthew Reed
### Game of snake, uses the D-Pad
### Adapted from https://pythonspot.com/snake-with-pygame/

import sys
import time
import signal
import logging
import configparser
from enum import Enum

import math
from random import randint
import matrix

class Snake:

    class Apple:
    
        def __init__(self, x, y):
            self.x = x
            self.y = y
     
        def draw(self, display):
            display.set_pixel(self.x, self.y, matrix.Colors.GREEN.value)
    
    class Player:

        class DIRECTION(Enum):
            NONE = 0
            UP = 1
            DOWN = 2
            LEFT = 3
            RIGHT = 4
     
        def __init__(self, length):
        
            self.length = length
            self.direction = self.DIRECTION.RIGHT
            
            self.updateCountMax = 4
            self.updateCount = 0

            # initial positions, no collision
            self.x = [2,1,0]
            self.y = [0,0,0]
            
            for i in range(0, 61):
                self.x.append(-100)
                self.y.append(-100)
     
        def update(self):
     
            self.updateCount = self.updateCount + 1
            if self.updateCount >= self.updateCountMax:
     
                # update previous positions
                for i in range(self.length, 0, -1):
                    self.x[i] = self.x[i-1]
                    self.y[i] = self.y[i-1]
     
                # update position of head of snake
                if self.direction == self.DIRECTION.RIGHT:
                    self.x[0] = self.x[0] + 1
                if self.direction == self.DIRECTION.LEFT:
                    self.x[0] = self.x[0] - 1
                if self.direction == self.DIRECTION.UP:
                    self.y[0] = self.y[0] - 1
                if self.direction == self.DIRECTION.DOWN:
                    self.y[0] = self.y[0] + 1
     
                self.updateCount = 0
                
        def is_overlaping(self, apple):
            for i in range(0, self.length):
                if apple.x == self.x[i] and apple.y == self.y[i]:
                    return True
            return False
     
        def draw(self, display):
            for i in range(0, self.length):
                #print("l: " + str(self.length) + " i: " + str(i) + " x: " + str(self.x[i]) + " y: " + str(self.y[i]))
                if self.x[i] > 7: self.x[i] = 7
                if self.x[i] < 0: self.x[i] = 0
                if self.y[i] > 7: self.y[i] = 7
                if self.y[i] < 0: self.y[i] = 0
                display.set_pixel(self.x[i], self.y[i], matrix.Colors.BLUE.value)

    def __init__(self, config, parent, matrix, controller):
        self.logger = logging.getLogger('snake')
        self.config = config
        self.parent = parent
        self.matrix = matrix
        self.controller = controller
        
    def reset(self):
        pass
        
    def splash(self):
    
        w = matrix.Colors.WHITE.value
        l = matrix.Colors.WHITE_LOW.value
        r = matrix.Colors.RED.value
        g = matrix.Colors.GREEN.value
        b = matrix.Colors.BLUE.value
        o = matrix.Colors.OFF.value
        
        splash = [
            [o, o, o, o, o, o, o, o],
            [o, o, b, b, b, o, g, o],
            [o, o, b, o, o, o, o, o],
            [o, o, b, b, b, o, o, o],
            [o, o, o, o, b, o, o, o],
            [o, o, b, b, b, o, o, o],
            [o, o, o, o, o, o, o, o],
            [o, o, o, o, o, o, o, o],
        ]
        
        for x in range(0, self.matrix.WIDTH):
            for y in range(0, self.matrix.HEIGHT):
                self.matrix.set_pixel(x, y, splash[y][x])
        
        self.matrix.update()
        
    def run(self):
    
        self.player = self.Player(3) 
        self.apple = self.Apple(5,5)
    
        #start timers and counters
        self.start_time = time.time()
        last_time = time.time()
        delay_time = 0.2
        
        led_iteration_count = 0
        frame_count = 0
        
        keep_going = True
        
        while keep_going:
            
            for event in self.controller.read_input():
                if event.code == 313 and event.value == 1:
                    keep_going = False
                elif event.code == 16:
                    if event.value == 1:
                        #dpad right
                        self.player.direction = self.player.DIRECTION.RIGHT
                    if event.value == 0:
                        #dpad none
                        pass
                    if event.value == -1:
                        #dpad left
                        self.player.direction = self.player.DIRECTION.LEFT
                elif event.code == 17:
                    if event.value == 1:
                        #dpad down
                        self.player.direction = self.player.DIRECTION.DOWN
                    if event.value == 0:
                        #dpad none
                        pass
                    if event.value == -1:
                        #dpad up
                        self.player.direction = self.player.DIRECTION.UP
            
            if time.time() > last_time + delay_time:
                last_time = time.time()
                
                #determine next move
                self.player.update()
         
                #does snake eat apple?
                if self.apple.x == self.player.x[0] and self.apple.y == self.player.y[0]:
                    self.player.length = self.player.length + 1
                    while self.player.is_overlaping(self.apple):
                        self.apple.x = randint(0, 7)
                        self.apple.y = randint(0, 7)
                    #go faster as the snake gets longer
                    delay_time = delay_time - 0.005
         
                #does snake collide with itself?
                for i in range(1, self.player.length):
                    if self.player.x[0] == self.player.x[i] and self.player.y[0] == self.player.y[i]:
                        print("You lose! Collision: ")
                        print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
                        print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")")
                        keep_going = False
                        
                #does snake go off the board?
                if self.player.x[0] < 0 or self.player.x[0] > 7 or self.player.y[0] < 0 or self.player.y[0] > 7:
                    print("You lose! Off Board: ")
                    print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
                    keep_going = False
                
                #update display
                self.matrix.set_matrix(matrix.Colors.OFF.value)
                self.player.draw(self.matrix)
                self.apple.draw(self.matrix)
                self.matrix.update()
                
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
                frame_count = frame_count + 1
                
            time.sleep(0.01)
        
        #display score before exiting
        self.matrix.set_matrix(matrix.Colors.OFF.value)
        self.matrix.update()
        for i in range(0, self.player.length):
            self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.WHITE.value)
        self.matrix.update()
        time.sleep(2)