Files @ 835bac5d3b3c
Branch filter:

Location: led-matrix-software/demos/pong.py - annotation

matthewreed
Added new demos and handle splash screens and controller input
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
835bac5d3b3c
### pong.py
### Author: Matthew Reed
### Game of pong, uses the D-Pad 
### Adapted from http://trevorappleton.blogspot.com/2014/04/writing-pong-using-python-and-pygame.html

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

import math
from random import randint
import matrix

class Pong:

    class Ball:
        
        def __init__(self, x, y):
            self.x = x
            self.y = y
            self.dir_x = -1 # -1=left 1=right
            self.dir_y = -1 # -1=up 1=down
            
        def move(self):
        
            self.x += self.dir_x
            self.y += self.dir_y
            
            #check for collision with wall and bounce
            if self.y <= 0:
                self.y = 0
                self.dir_y = 1
            elif self.y >= 7:
                self.y = 7
                self.dir_y = -1
            
        def draw(self, display):
            display.set_pixel(self.x, self.y, matrix.Colors.RED.value)
            
    
    class Paddle:

        class DIRECTION(Enum):
            NONE = 0
            UP = 1
            DOWN = 2
            LEFT = 3
            RIGHT = 4
        
        def __init__(self, x, y):
            self.size = 3
            self.x = x
            self.position = y
            self.direction = self.DIRECTION.NONE
            
        def move(self):
            if self.direction == self.DIRECTION.UP:
                self.position = self.position - 1
                if self.position < 0:
                    self.position = 0
            elif self.direction == self.DIRECTION.DOWN:
                self.position = self.position + 1
                if self.position + self.size > 8:
                    self.position = 8 - self.size
            
        def auto_move(self, ball):
            #If ball is moving away from paddle, center
            if ball.dir_x == -1:
                if self.position < 3:
                    self.position += 1
                elif self.position > 3:
                    self.position -= 1
            #if ball moving towards paddle, track its movement
            elif ball.dir_x == 1:
                if self.position + 1 - ball.dir_y < ball.y:
                    self.position += 1
                elif self.position + 1 - ball.dir_y > ball.y:
                    self.position -= 1
                    
            if self.position < 0:
                self.position = 0
            elif self.position + self.size > 8:
                self.position = 8 - self.size
            
        def draw(self, display):
            for i in range(0, self.size):
                display.set_pixel(self.x, self.position + 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
        b = matrix.Colors.BLUE.value
        o = matrix.Colors.OFF.value
        
        splash = [
            [l, l, l, l, l, l, l, l],
            [l, o, o, o, o, o, o, l],
            [b, o, o, o, o, o, o, l],
            [b, o, o, o, r, o, o, b],
            [b, o, o, o, o, o, o, b],
            [l, o, o, o, o, o, o, b],
            [l, o, o, o, o, o, o, l],
            [l, l, l, l, l, l, l, l],
        ]
        
        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):
        
        #start timers and counters
        self.start_time = time.time()
        last_time = time.time()
        delay_time = 0.1
        
        led_iteration_count = 0
        frame_count = 0
            
        self.updateBallCountMax = 5
        self.updateBallCount = 0
        self.updateCompCountMax = 10
        self.updateCompCount = 0
        
        ball = self.Ball(4, 3)
        paddle1 = self.Paddle(0, 3)
        paddle2 = self.Paddle(7, 3)
        
        score = 0
        
        #draw display
        self.matrix.set_matrix(matrix.Colors.OFF.value)
        
        for x in range(0, 8):
            self.matrix.set_pixel(x, 0, matrix.Colors.WHITE_LOW.value)
            self.matrix.set_pixel(x, 7, matrix.Colors.WHITE_LOW.value)
        for y in range(0, 8):
            self.matrix.set_pixel(0, y, matrix.Colors.WHITE_LOW.value)
            self.matrix.set_pixel(3, y, matrix.Colors.WHITE_LOW.value)
            self.matrix.set_pixel(4, y, matrix.Colors.WHITE_LOW.value)
            self.matrix.set_pixel(7, y, matrix.Colors.WHITE_LOW.value)
            
        paddle1.draw(self.matrix)
        paddle2.draw(self.matrix)
        ball.draw(self.matrix)
        
        self.matrix.update()
        
        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 == 17:
                    if event.value == 1:
                        #dpad down
                        paddle1.direction = self.Paddle.DIRECTION.DOWN
                    if event.value == 0:
                        #dpad none
                        paddle1.direction = self.Paddle.DIRECTION.NONE
                        pass
                    if event.value == -1:
                        #dpad up
                        paddle1.direction = self.Paddle.DIRECTION.UP
            
            if time.time() > last_time + delay_time:
                last_time = time.time()
                
                paddle1.move()
        
                self.updateBallCount = self.updateBallCount + 1
                if self.updateBallCount >= self.updateBallCountMax:
                    ball.move()
                
                    self.updateBallCount = 0
                
                self.updateCompCount = self.updateCompCount + 1
                if self.updateCompCount >= self.updateCompCountMax:
                    paddle2.auto_move(ball)
                
                    self.updateCompCount = 0
                
                #ball hits paddle 1
                if ball.dir_x == -1 and ball.x == 1:
                    ball.dir_x = ball.dir_x *  -1
                    # if the ball bounces off the corner of the paddle, it goes back in the same direction it came from
                    if (ball.dir_y == 1 and ball.y == paddle1.position) or (ball.dir_y == -1 and ball.y == paddle1.position + 2):
                        ball.dir_y = ball.dir_y *  -1
                        
                    # if the paddle is in motion, give the ball some translation
                    if paddle1.direction == self.Paddle.DIRECTION.DOWN:
                        if ball.y < 7:
                            ball.y = ball.y + 1
                            if ball.y >= 7:
                                ball.y = 7
                                ball.dir_y = -1
                    elif paddle1.direction == self.Paddle.DIRECTION.UP:
                        if ball.y > 0:
                            ball.y = ball.y - 1
                            if ball.y <= 0:
                                ball.y = 0
                                ball.dir_y = 1
                    
                elif ball.dir_x == -1 and ball.x == 0:
                    if paddle1.position <= ball.y and (paddle1.position + paddle1.size) > ball.y:
                        #1 point for hitting the ball
                        score += 1
                        print("Hit!")
                    else:
                        #game over if left wall is hit
                        print("Miss!")
                        keep_going = False
                        
                elif ball.dir_x == 1 and ball.x == 6:
                    ball.dir_x = ball.dir_x *  -1
                    if paddle2.position <= ball.y and (paddle2.position + paddle2.size) > ball.y:
                        #ball hits paddle2
                        pass
                elif ball.dir_x == 1 and ball.x == 7:
                    #5 points for beating paddle2
                    score += 5
                    print("Score!")
                
                #update display
                self.matrix.set_matrix(matrix.Colors.OFF.value)
                
                #draw game background
                for x in range(0, 8):
                    self.matrix.set_pixel(x, 0, matrix.Colors.WHITE_LOW.value)
                    self.matrix.set_pixel(x, 7, matrix.Colors.WHITE_LOW.value)
                for y in range(0, 8):
                    self.matrix.set_pixel(0, y, matrix.Colors.WHITE_LOW.value)
                    self.matrix.set_pixel(3, y, matrix.Colors.WHITE_LOW.value)
                    self.matrix.set_pixel(4, y, matrix.Colors.WHITE_LOW.value)
                    self.matrix.set_pixel(7, y, matrix.Colors.WHITE_LOW.value)
                    
                paddle1.draw(self.matrix)
                paddle2.draw(self.matrix)
                ball.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)
        if score > 750:
            for i in range(0, 64):
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.YELLOW.value)
        else:
            multiples = math.floor(score / 50)
            score = score % 50
            for i in range(0, multiples):
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.YELLOW.value)
            for i in range(multiples, score):
                self.matrix.set_pixel(i % self.matrix.WIDTH, math.floor(i / self.matrix.HEIGHT), matrix.Colors.WHITE.value)
        self.matrix.update()
        time.sleep(2)