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)