Changeset - 835bac5d3b3c
[Not reviewed]
tip default
0 7 3
Matthew Reed (matthewreed) - 6 years ago 2019-05-24 13:58:02
matthewreed64@gmail.com
Added new demos and handle splash screens and controller input
10 files changed with 808 insertions and 9 deletions:
0 comments (0 inline, 0 general)
controller.py
Show inline comments
 
@@ -30,14 +30,16 @@ class Controller:
 
    def read_input(self):
 
        
 
        if self.dev == None:
 
            self.connect()
 
        
 
        events = []
 
        if self.dev != None:
 
            try:
 
                for event in self.dev.read():
 
                    events.append(event)
 
            except BlockingIOError:
 
                pass
 
            except OSError:
 
                self.dev = None
 
            
 
        return events
 
\ No newline at end of file
demos/__init__.py
Show inline comments
 
__all__ = ['paint', 'rainbow', 'snake']
 
\ No newline at end of file
 
__all__ = ['rainbow', 'paint', 'snake', 'pong', 'tetris', 'clouds']
 
\ No newline at end of file
demos/clouds.py
Show inline comments
 
new file 100644
 
### clouds.py
 
### Author: Matthew Reed
 
### Random noise generated colors
 
### Adapted from https://github.com/scanlime/fadecandy/blob/master/examples/processing/grid24x8z_clouds/grid24x8z_clouds.pde
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
import matrix
 
import noise
 
import color_utils
 
import random
 
 
class Clouds:
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('paint')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
    
 
        r = matrix.Colors.RED.value
 
        o = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        p = matrix.Colors.PURPLE.value
 
        w = matrix.Colors.WHITE.value
 
        v = matrix.Colors.VIOLET.value
 
        l = matrix.Colors.LIGHT_BLUE.value
 
        m = matrix.Colors.MAGENTA.value
 
        q = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, r, w, p, v, q, q],
 
            [q, q, b, g, o, m, q, q],
 
            [q, q, r, p, y, l, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
        ]
 
        
 
        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 hsv_to_rgb(self, h, s, v):
 
        if s == 0.0: return (v, v, v)
 
        i = int(h*6.) # XXX assume int() truncates!
 
        f = (h*6.)-i; p,q,t = v*(1.-s), v*(1.-s*f), v*(1.-s*(1.-f)); i%=6
 
        if i == 0: return (v, t, p)
 
        if i == 1: return (q, v, p)
 
        if i == 2: return (p, v, t)
 
        if i == 3: return (p, q, v)
 
        if i == 4: return (t, p, v)
 
        if i == 5: return (v, p, q)
 
        
 
 
    def fractalNoise(self, x, y, z):
 
      r = 0
 
      amp = 1.0
 
      for octave in range(4):
 
        r += noise.pnoise3(x, y, z) * amp;
 
        amp /= 2;
 
        x *= 2;
 
        y *= 2;
 
        z *= 2;
 
      return r;
 
      
 
    def constrain(self, val, min_val, max_val):
 
        return min(max_val, max(min_val, val))
 
        
 
    def run(self):
 
    
 
        dx = 0.0
 
        dy = 0.0
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        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
 
            
 
            if time.time() > last_time + 1:
 
                last_time = time.time()
 
                
 
                
 
                now = time.time()
 
                speed = 0.002
 
                angle = math.sin(now)
 
                z = now * 0.08
 
                hue = now * 10
 
                scale = 0.005;
 
 
                dx += math.cos(angle) * speed
 
                dy += math.sin(angle) * speed
 
 
                for x in range(self.matrix.WIDTH):
 
                    for y in range(self.matrix.HEIGHT):
 
 
                        n = self.fractalNoise(dx + x*scale, dy + y*scale, z) - 0.75
 
                        m = self.fractalNoise(dx + x*scale, dy + y*scale, z + 10.0) - 0.75
 
 
                        color = self.hsv_to_rgb(
 
                            (hue + 80.0 * m) % 256.0, 
 
                            256 - 256 * self.constrain(pow(3.0 * abs(n), 3.5), 0, 0.9), 
 
                            256 * self.constrain(pow(3.0 * abs(n), 1.5), 0, 0.9)
 
                        )
 
 
                        self.matrix.set_pixel(x, y, color)
 
                
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
\ No newline at end of file
demos/paint.py
Show inline comments
 
@@ -23,25 +23,52 @@ class Paint:
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('paint')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
        self.matrix.set_matrix((255,0,0))
 
    
 
        w = matrix.Colors.WHITE.value
 
        r = matrix.Colors.RED.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        l = matrix.Colors.LIGHT_BLUE.value
 
        p = matrix.Colors.PURPLE.value
 
        O = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        v = matrix.Colors.VIOLET.value
 
        m = matrix.Colors.MAGENTA.value
 
        o = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [o, o, o, o, o, o, o, o],
 
            [o, o, w, w, w, o, o, o],
 
            [o, o, w, o, w, o, o, o],
 
            [o, o, w, w, w, o, o, o],
 
            [o, o, w, o, o, r, O, y],
 
            [o, o, w, o, o, m, w, g],
 
            [o, o, w, o, o, v, b, l],
 
            [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):
 
    
 
        pointer = 0
 
        direction = self.DIRECTION.NONE
 
        color = matrix.Colors.WHITE.value
 
        color_index = 7
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
demos/pong.py
Show inline comments
 
new file 100644
 
### 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)
 
\ No newline at end of file
demos/rainbow.py
Show inline comments
 
### rainbow.py
 
### Author: Matthew Reed
 
### Rainbow array scrolls across the display. Rainbow generated using overlapping sin waves. The frequency, phase shift, center, and width all affect the output.
 
### Inspired by https://krazydad.com/tutorials/makecolors.php
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
import matrix
 
 
class Rainbow:
 
 
    class MODES(Enum):
 
        TWO_D = 0
 
        LINEAR = 1
 
        SOLID = 2
 
 
    def __init__(self, config, parent, matrix, controller):
 
        self.logger = logging.getLogger('paint')
 
        self.config = config
 
        self.parent = parent
 
        self.matrix = matrix
 
        self.controller = controller
 
        
 
    def reset(self):
 
        pass
 
        
 
    def splash(self):
 
        self.matrix.set_matrix((0,255,0))
 
    
 
        r = matrix.Colors.RED.value
 
        o = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        p = matrix.Colors.PURPLE.value
 
        q = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, r, o, y, g, b, p, q],
 
            [q, r, o, y, g, b, p, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
            [q, q, q, q, q, q, q, q],
 
        ]
 
        
 
        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):
 
    
 
        center = 128;
 
        width = 100;
 
        width = 127;
 
        frequency = .1;
 
    
 
        mode = self.MODES.TWO_D
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        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 == 305 and event.value == 1:
 
                    mode = self.MODES((mode.value + 1) % len(self.MODES))
 
                elif event.code == 16:
 
                    if event.value == 1:
 
                        #dpad right
 
                        pass
 
                    if event.value == -1:
 
                        #dpad left
 
                        pass
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        frequency = frequency - 0.05
 
                        if frequency <= 0.05:
 
                            frequency = 0.05
 
                        print(frequency)
 
                    if event.value == -1:
 
                        #dpad up
 
                        frequency = frequency + 0.05
 
                        if frequency >= 1:
 
                            frequency = 1
 
                        print(frequency)
 
                        
 
            
 
            if time.time() > last_time + 0.1:
 
                last_time = time.time()
 
                    
 
                for y in range(self.matrix.HEIGHT):
 
                    phaseShift = 2*math.pi - y*(1.5*math.pi/(self.matrix.HEIGHT-1))
 
                    if mode == self.MODES.TWO_D:
 
                        phaseShift = 2*math.pi - y*(math.pi/(self.matrix.HEIGHT-1))
 
                    else:
 
                        phaseShift = 4
 
                    for x in range(self.matrix.WIDTH):
 
                        if mode == self.MODES.SOLID:
 
                            i = frame_count % 128
 
                        else:
 
                        i = (x + frame_count) % 128
 
                        red = math.sin(frequency*i + 0) * width + center;
 
                        green = math.sin(frequency*i + phaseShift/2) * width + center;
 
                        blue = math.sin(frequency*i + phaseShift) * width + center;
 
                        
 
                        self.matrix.set_pixel(x, y, (red, green, blue))
 
                
 
                self.matrix.update()
 
                
 
                led_iteration_count = (led_iteration_count + 1) % self.matrix.NUM_LEDS
 
                frame_count = frame_count + 1
 
                
 
            time.sleep(0.01)
 
\ No newline at end of file
 
            time.sleep(0.01)
demos/snake.py
Show inline comments
 
### snake.py
 
### Author: Matthew Reed
 
### Game of snake, uses the D-Pad
 
### Adapted from https://pythonspot.com/snake-with-pygame/ ###
 
### 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
 
 
@@ -89,25 +89,47 @@ class Snake:
 
 
    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):
 
        self.matrix.set_matrix(matrix.Colors.BLUE.value)
 
    
 
        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
 
        
demos/tetris.py
Show inline comments
 
new file 100644
 
### tetris.py
 
### Author: Matthew Reed
 
### Game of tetris, uses the D-Pad
 
### Adapted from https://gist.github.com/silvasur/565419/d9de6a84e7da000797ac681976442073045c74a4
 
 
import sys
 
import time
 
import signal
 
import logging
 
import configparser
 
from enum import Enum
 
 
import math
 
from random import randrange as rand
 
import matrix
 
 
class Tetris:
 
 
    # Define the shapes of the single parts
 
    tetris_shapes = [
 
        [[1, 1, 1],
 
         [0, 1, 0]],
 
 
        [[0, 2, 2],
 
         [2, 2, 0]],
 
 
        [[3, 3, 0],
 
         [0, 3, 3]],
 
 
        [[4, 0, 0],
 
         [4, 4, 4]],
 
 
        [[0, 0, 5],
 
         [5, 5, 5]],
 
 
        [[6, 6, 6, 6]],
 
 
        [[7, 7],
 
         [7, 7]]
 
    ]
 
    
 
    colors = [
 
        matrix.Colors.OFF.value,
 
        matrix.Colors.RED.value,
 
        matrix.Colors.GREEN.value,
 
        matrix.Colors.BLUE.value,
 
        matrix.Colors.ORANGE.value,
 
        matrix.Colors.YELLOW.value,
 
        matrix.Colors.MAGENTA.value,
 
        matrix.Colors.LIGHT_BLUE.value
 
    ]
 
    
 
    def rotate_clockwise(self, shape):
 
        return [[ shape[y][x] for y in range(len(shape)) ] for x in range(len(shape[0]) - 1, -1, -1)]
 
 
    def check_collision(self, board, shape, offset):
 
        off_x, off_y = offset
 
        for cy, row in enumerate(shape):
 
            for cx, cell in enumerate(row):
 
                try:
 
                    if cell and board[ cy + off_y ][ cx + off_x ]:
 
                        return True
 
                except IndexError:
 
                    return True
 
        return False
 
 
    def remove_row(self, board, row):
 
        del board[row]
 
        self.score += 1
 
        return [[0 for i in range(self.width)]] + board
 
 
    def join_matrixes(self, mat1, mat2, mat2_off):
 
        off_x, off_y = mat2_off
 
        for cy, row in enumerate(mat2):
 
            for cx, val in enumerate(row):
 
                mat1[cy+off_y-1	][cx+off_x] += val
 
        return mat1
 
 
    def new_board(self):
 
        board = [[0 for x in range(self.width)] for y in range(self.height)]
 
        board += [[1 for x in range(self.width)]]
 
        return board
 
        
 
    def new_stone(self):
 
        self.stone = self.tetris_shapes[rand(len(self.tetris_shapes))]
 
        self.stone_x = int(self.width / 2 - len(self.stone[0])/2)
 
        self.stone_y = 0
 
        
 
        if self.check_collision(self.board, self.stone, (self.stone_x, self.stone_y)):
 
            self.gameover = True
 
 
    def draw(self, matrix, board, offset):
 
        off_x, off_y  = offset
 
        for y, row in enumerate(board):
 
            for x, val in enumerate(row):
 
                if val and y < self.height:
 
                    matrix.set_pixel(off_x + x, off_y + y, self.colors[val])
 
 
    def move(self, delta_x):
 
        if not self.gameover and not self.paused:
 
            new_x = self.stone_x + delta_x
 
            if new_x < 0:
 
                new_x = 0
 
            if new_x > self.width - len(self.stone[0]):
 
                new_x = self.width - len(self.stone[0])
 
            if not self.check_collision(self.board, self.stone, (new_x, self.stone_y)):
 
                self.stone_x = new_x
 
 
    def drop(self):
 
        if not self.gameover and not self.paused:
 
            self.stone_y += 1
 
            if self.check_collision(self.board, self.stone, (self.stone_x, self.stone_y)):
 
                self.board = self.join_matrixes(self.board, self.stone, (self.stone_x, self.stone_y))
 
                self.new_stone()
 
                while True:
 
                    for i, row in enumerate(self.board[:-1]):
 
                        if 0 not in row:
 
                            self.board = self.remove_row(self.board, i)
 
                            break
 
                    else:
 
                        break
 
 
    def rotate_stone(self):
 
        if not self.gameover and not self.paused:
 
            new_stone = self.rotate_clockwise(self.stone)
 
            if not self.check_collision(self.board, new_stone, (self.stone_x, self.stone_y)):
 
                self.stone = new_stone
 
 
    def toggle_pause(self):
 
        self.paused = not self.paused
 
 
    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
 
        r = matrix.Colors.RED.value
 
        g = matrix.Colors.GREEN.value
 
        b = matrix.Colors.BLUE.value
 
        l = matrix.Colors.LIGHT_BLUE.value
 
        m = matrix.Colors.MAGENTA.value
 
        O = matrix.Colors.ORANGE.value
 
        y = matrix.Colors.YELLOW.value
 
        o = matrix.Colors.OFF.value
 
        
 
        splash = [
 
            [o, o, o, o, o, o, y, y],
 
            [o, g, g, g, g, g, o, y],
 
            [o, g, o, g, o, g, o, y],
 
            [o, o, o, g, o, o, l, l],
 
            [o, o, o, g, o, o, l, l],
 
            [r, o, o, g, o, o, b, O],
 
            [r, r, g, g, g, b, b, O],
 
            [r, m, m, m, m, b, 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.width = 8
 
        self.height = 8
 
        
 
        self.board = self.new_board()
 
        self.new_stone()
 
    
 
        #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.updateCountMax = 15
 
        self.updateCount = 0
 
        
 
        self.score = 0
 
        
 
        self.gameover = False
 
        self.paused = False
 
        
 
        while not self.gameover:
 
            
 
            for event in self.controller.read_input():
 
                if event.code == 313 and event.value == 1:
 
                    #start button
 
                    self.gameover = True
 
                if event.code == 305 and event.value == 1:
 
                    #A button
 
                    self.toggle_pause()
 
                elif event.code == 16:
 
                    if event.value == 1:
 
                        #dpad right
 
                        self.move(+1)
 
                    if event.value == 0:
 
                        #dpad none
 
                        pass
 
                    if event.value == -1:
 
                        #dpad left
 
                        self.move(-1)
 
                elif event.code == 17:
 
                    if event.value == 1:
 
                        #dpad down
 
                        self.drop()
 
                    if event.value == 0:
 
                        #dpad none
 
                        pass
 
                    if event.value == -1:
 
                        #dpad up
 
                        self.rotate_stone()
 
            
 
            if time.time() > last_time + delay_time:
 
                last_time = time.time()
 
                
 
                self.updateCount = self.updateCount + 1
 
                if self.updateCount >= self.updateCountMax:
 
                    self.drop()
 
                    self.updateCount = 0
 
                
 
                #update display
 
                self.matrix.set_matrix(matrix.Colors.OFF.value)
 
                self.draw(self.matrix, self.board, (0,0))
 
                self.draw(self.matrix, self.stone, (self.stone_x, self.stone_y))
 
                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 self.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(self.score / 50)
 
            self.score = self.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, self.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)
 
\ No newline at end of file
lights.py
Show inline comments
 
@@ -22,45 +22,50 @@ from demos import *
 
 
class Lights:
 
 
    def __init__(self, config):
 
        self.logger = logging.getLogger('lights.lights')
 
        self.config = config
 
        
 
        self.matrix = matrix.Matrix(config)
 
        self.controller = controller.Controller(config)
 
        
 
        self.demo_i = 0
 
        self.demos = [
 
                rainbow.Rainbow(self.config, self, self.matrix, self.controller),
 
                paint.Paint(self.config, self, self.matrix, self.controller),
 
                rainbow.Rainbow(self.config, self, self.matrix, self.controller),
 
                snake.Snake(self.config, self, self.matrix, self.controller),
 
                pong.Pong(self.config, self, self.matrix, self.controller),
 
                tetris.Tetris(self.config, self, self.matrix, self.controller),
 
                clouds.Clouds(self.config, self, self.matrix, self.controller),
 
            ]
 
    
 
    def reset(self):
 
    
 
        self.color = matrix.Colors.WHITE.value
 
        self.matrix.set_matrix(matrix.Colors.OFF.value)
 
        
 
    def run(self):
 
        
 
        self.reset()
 
    
 
        #start timers and counters
 
        self.start_time = time.time()
 
        last_time = time.time()
 
        
 
        led_iteration_count = 0
 
        frame_count = 0
 
        
 
        self.demos[self.demo_i].run()
 
        
 
        while True:
 
            
 
            for event in self.controller.read_input():
 
                #print("Event: " + str(event))
 
                if event.code == 312 and event.value == 1:
 
                    self.demo_i = (self.demo_i + 1) % len(self.demos)
 
                    self.reset()
 
                elif event.code == 313 and event.value == 1:
 
                    self.reset()
 
                    self.demos[self.demo_i].run()
 
            
 
            if time.time() > last_time + 0.1:
matrix.py
Show inline comments
 
@@ -10,27 +10,30 @@ import configparser
 
from enum import Enum
 
 
import opc
 
import color_utils
 
import math
 
 
 
class Colors(Enum):
 
    OFF = (0, 0, 0)
 
    RED = (255, 0, 0)
 
    GREEN = (0, 255, 0)
 
    BLUE = (0, 0, 255)
 
    LIGHT_BLUE = (0, 220, 220)
 
    PURPLE = (128, 0, 128)
 
    VIOLET = (148, 0, 211)
 
    YELLOW = (255, 255, 0)
 
    ORANGE = (255, 140, 0)
 
    MAGENTA = (255, 0, 255)
 
    WHITE = (255, 255, 255)
 
    WHITE_LOW = (100, 100, 100)
 
 
class Matrix:
 
 
    def __init__(self, config):
 
        self.logger = logging.getLogger('matrix')
 
        self.config = config
 
        
 
        #init leds
 
        self.ADDRESS = 'localhost:7890'
 
        # Create a client object
0 comments (0 inline, 0 general)