Pong met 3×6 Color Light Matrix

De LEGO® EDUCATION SPIKE™ 3×3 Color Light Matrix [45608]: “Voor gebruik met LEGO® Technic hubs kan elk van de 9 pixels worden geprogrammeerd om 10 verschillende kleuren en 10 helderheidsniveaus weer te geven voor eindeloze creatieve mogelijkheden.”.

Dat gaat een beetje de kant op van die geweldige Ulanzi TC001 pixel display (maar dan wel aanzienlijk kostbaarder: ze kosten 50 EUR per stuk).

Co-pilot timmerde daar vlot een Pong programma voor in elkaar.

from pybricks.hubs import InventorHub
from pybricks.pupdevices import ColorLightMatrix, ForceSensor
from pybricks.parameters import Port, Color
from pybricks.tools import wait
from urandom import choice

LEFT_MATRIX_PORT  = Port.C   # Linker 3×3 matrix
RIGHT_MATRIX_PORT = Port.E   # Rechter 3×3 matrix
RIGHT_UP_PORT     = Port.B   # Omhoog
RIGHT_DOWN_PORT   = Port.D   # Omlaag
FPS              = 1      
BASE_TICK_MS     = int(1000 / FPS)
MIN_TICK_MS      = 120
BALL_COLOR       = Color.YELLOW
LEFT_PADDLE_COL  = Color.GREEN
RIGHT_PADDLE_COL = Color.RED
OFF_COLOR        = Color.BLACK
SCORE_FLASH_MS   = 600
START_COLOR_TEST = True   
DEMO_GRID        = False  

hub = InventorHub()

left_matrix  = ColorLightMatrix(LEFT_MATRIX_PORT)
right_matrix = ColorLightMatrix(RIGHT_MATRIX_PORT)
right_up_btn   = ForceSensor(RIGHT_UP_PORT)
right_down_btn = ForceSensor(RIGHT_DOWN_PORT)

def new_frame():
    return [[OFF_COLOR for _ in range(3)] for _ in range(3)]

def set_pixel_on_matrices(x, y, color, frame_left, frame_right):
    if not (0 <= x <= 5 and 0 <= y <= 2):
        return
    if x < 3:
        frame_left[y][x] = color
    else:
        frame_right[y][x - 3] = color

def render(frame_left, frame_right):
    buf_left  = [c for row in frame_left  for c in row]
    buf_right = [c for row in frame_right for c in row]
    left_matrix.on(buf_left)
    right_matrix.on(buf_right)

def clear_displays():
    left_matrix.off()
    right_matrix.off()

def start_diagnose():
    if START_COLOR_TEST:
        left_matrix.on([Color.YELLOW] * 9)
        right_matrix.on([Color.VIOLET] * 9)
        wait(200)
        clear_displays()

    if DEMO_GRID:
        fl = new_frame()
        fr = new_frame()
        for y in range(3):
            for x in range(6):
                c = Color.GREEN if (x + y) % 2 == 0 else Color.MAGENTA
                set_pixel_on_matrices(x, y, c, fl, fr)
        render(fl, fr)
        wait(800)
        clear_displays()

def reset_round(server="left"):
    ball = {"x": 2, "y": 1, "dx": 1 if server == "left" else -1, "dy": choice([-1, 1])}
    return ball

left_paddle_y  = 1   # AI links
right_paddle_y = 1   # speler rechts
left_score     = 0
right_score    = 0
server         = "left"
ball           = reset_round(server)
prev_up_pressed   = False
prev_down_pressed = False
AI_MOVE_EVERY_N_TICKS = 1
ai_tick_counter       = 0

start_diagnose()

while True:
    tick_ms = max(BASE_TICK_MS, MIN_TICK_MS)
    up_now   = bool(right_up_btn.pressed(force=4))
    down_now = bool(right_down_btn.pressed(force=4))

    if up_now and not prev_up_pressed:
        right_paddle_y = (right_paddle_y - 1) % 3

    if down_now and not prev_down_pressed:
        right_paddle_y = (right_paddle_y + 1) % 3

    prev_up_pressed   = up_now
    prev_down_pressed = down_now

    ai_tick_counter = (ai_tick_counter + 1) % AI_MOVE_EVERY_N_TICKS
    if ai_tick_counter == 0 and ball["dx"] < 0:
        if ball["y"] < left_paddle_y:
            left_paddle_y = (left_paddle_y - 1) % 3
        elif ball["y"] > left_paddle_y:
            left_paddle_y = (left_paddle_y + 1) % 3

    next_x = ball["x"] + ball["dx"]
    next_y = ball["y"] + ball["dy"]

    if next_y < 0 or next_y > 2:
        ball["dy"] *= -1
        next_y = ball["y"] + ball["dy"]

    scored = None
    if next_x < 0:
        if ball["y"] == left_paddle_y:
            ball["dx"] = 1
            next_x = ball["x"] + ball["dx"]
        else:
            scored = "right"
    elif next_x > 5:
        if ball["y"] == right_paddle_y:
            ball["dx"] = -1
            next_x = ball["x"] + ball["dx"]
        else:
            scored = "left"

    if scored:
        if scored == "left":
            left_score += 1
        else:
            right_score += 1

        win_color  = Color.GREEN
        lose_color = Color.RED
        if scored == "left":
            left_frame  = [[win_color]*3  for _ in range(3)]
            right_frame = [[lose_color]*3 for _ in range(3)]
        else:
            left_frame  = [[lose_color]*3 for _ in range(3)]
            right_frame = [[win_color]*3  for _ in range(3)]
        render(left_frame, right_frame)
        wait(SCORE_FLASH_MS)

        server = scored
        ball   = reset_round(server)
        clear_displays()
        wait(180)
    else:
        ball["x"] = next_x
        ball["y"] = next_y
        fl = new_frame()
        fr = new_frame()
        set_pixel_on_matrices(0, left_paddle_y,  LEFT_PADDLE_COL,  fl, fr)
        set_pixel_on_matrices(5, right_paddle_y, RIGHT_PADDLE_COL, fl, fr)
        set_pixel_on_matrices(ball["x"], ball["y"], BALL_COLOR, fl, fr)
        render(fl, fr)
        wait(tick_ms)

Geef een reactie

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

Previous post Lego Mosaic
Next post Azure translate service