Files @ 835bac5d3b3c
Branch filter:

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

matthewreed
Added new demos and handle splash screens and controller input
### 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)