snake_computer/main.py
2025-05-26 01:14:37 +02:00

298 lines
7.0 KiB
Python

import neopixel
from machine import Pin
import time
from random import random, seed, choice
seed()
ws_pin = 0
led_zahl = 64
helligkeit = 0.05
matrix = neopixel.NeoPixel(Pin(ws_pin), led_zahl)
taster_hoch = Pin(1, Pin.IN, Pin.PULL_UP)
taster_runter = Pin(2, Pin.IN, Pin.PULL_UP)
taster_rechts = Pin(3, Pin.IN, Pin.PULL_UP)
taster_links = Pin(4, Pin.IN, Pin.PULL_UP)
scalar = float # a scale value (0.0 to 1.0)
def hsv2rgb(h:scalar, s:scalar, v:scalar) -> tuple:
if s:
if h == 1.0: h = 0.0
i = int(h*6.0); f = h*6.0 - i
w = int(255*( v * (1.0 - s) ))
q = int(255*( v * (1.0 - s * f) ))
t = int(255*( v * (1.0 - s * (1.0 - f)) ))
v = int(255*v)
if i==0: return (v, t, w)
if i==1: return (q, v, w)
if i==2: return (w, v, t)
if i==3: return (w, q, v)
if i==4: return (t, w, v)
if i==5: return (v, w, q)
else: v = int(255*v); return (v, v, v)
def zufall_farbe():
return hsv2rgb(random(), 1.0, 1.0)
def setze_helligkeit(farbe):
r, g, b = farbe
r = int(r * helligkeit)
g = int(g * helligkeit)
b = int(b * helligkeit)
return (r, g, b)
def setze_pixel(x, y, farbe):
farbe = setze_helligkeit(farbe)
i = y * 8 + x
matrix[i] = farbe
def neue_richtung(t):
richtung = None
for i in range(1, 10):
if not taster_runter.value():
richtung = "runter"
if not taster_rechts.value():
richtung = "rechts"
if not taster_links.value():
richtung = "links"
if not taster_hoch.value():
richtung = "hoch"
time.sleep(t/10)
return richtung
def warte_auf_taste():
richtung = "vor"
i = 0
taste = None
schwierigkeit = 1
while taste != "rechts":
taste = neue_richtung(0.2)
matrix.fill((0, 0, 0))
if i == 0:
richtung = "vor"
if i == 7:
richtung = "zurueck"
if richtung == "vor":
i = i+1
elif richtung == "zurueck":
i = i-1
setze_pixel(i, 0, (255, 0, 0))
setze_pixel(7, i, (0, 255, 0))
setze_pixel(7-i, 7, (0, 0, 255))
setze_pixel(0, 7-i, (255, 255, 0))
if taste == "runter":
schwierigkeit = schwierigkeit + 1
if schwierigkeit == 4: schwierigkeit = 3
if taste == "hoch":
schwierigkeit = schwierigkeit - 1
if schwierigkeit == 0: schwierigkeit = 1
gruen = (0, 255, 0)
gelb = (255, 255, 0)
rot = (255, 0, 0)
if schwierigkeit == 1:
setze_pixel(3, 1, gruen)
setze_pixel(4, 1, gruen)
setze_pixel(3, 2, gruen)
setze_pixel(4, 2, gruen)
if schwierigkeit == 2:
setze_pixel(3, 3, gelb)
setze_pixel(4, 3, gelb)
setze_pixel(3, 4, gelb)
setze_pixel(4, 4, gelb)
if schwierigkeit == 3:
setze_pixel(3, 5, rot)
setze_pixel(4, 5, rot)
setze_pixel(3, 6, rot)
setze_pixel(4, 6, rot)
matrix.write()
return schwierigkeit
RICHTUNGEN = {
"hoch": (0, -1),
"runter": (0, 1),
"links": (-1, 0),
"rechts": (1, 0)
}
SCHWIERIGKEITEN = [0.6, 0.4, 0.3]
def ist_entgegengesetzt(r1, r2):
if r1 == "hoch" and r2 == "runter":
return True
if r1 == "links" and r2 == "rechts":
return True
if r1 == "rechts" and r2 == "links":
return True
if r1 == "runter" and r2 == "hoch":
return True
return False
def anzeigen(snake, essen):
matrix.fill((0, 0, 0))
# Snake anzeigen
length = len(snake)
for i, (x, y) in enumerate(snake):
hue = (i / length) % 1.0 # Spread hue over the snake's body
color = hsv2rgb(hue, 1.0, 1.0)
setze_pixel(x, y, color)
# Essen anzeigen
fx, fy = essen
setze_pixel(fx, fy, (255, 255, 255))
matrix.write()
def neues_essen(snake):
leere_felder = [(x, y) for x in range(8) for y in range(8) if (x, y) not in snake]
return choice(leere_felder)
def draw_x_pattern(color):
for i in range(8):
setze_pixel(i, i, color)
setze_pixel(i, 7 - i, color)
matrix.write()
DIGIT_PATTERNS = {
'0': ["###",
"# #",
"# #",
"# #",
"###"],
'1': [" #",
" #",
" #",
" #",
" #"],
'2': ["###",
" #",
"###",
"# ",
"###"],
'3': ["###",
" #",
"###",
" #",
"###"],
'4': ["# #",
"# #",
"###",
" #",
" #"],
'5': ["###",
"# ",
"###",
" #",
"###"],
'6': ["###",
"# ",
"###",
"# #",
"###"],
'7': ["###",
" #",
" #",
" #",
" #"],
'8': ["###",
"# #",
"###",
"# #",
"###"],
'9': ["###",
"# #",
"###",
" #",
"###"]
}
def draw_digit(digit, x_offset, y_offset, color):
pattern = DIGIT_PATTERNS.get(str(digit), [" "]*5)
for y, row in enumerate(pattern):
for x, char in enumerate(row):
if char == '#':
px = x + x_offset
py = y + y_offset
if 0 <= px < 8 and 0 <= py < 8:
setze_pixel(px, py, color)
def game_over(score):
red = (255, 0, 0)
black = (0, 0, 0)
# Flash X pattern
matrix.fill(black)
flashes = 3
for _ in range(flashes):
draw_x_pattern(red)
time.sleep(0.3)
draw_x_pattern(black)
time.sleep(0.2)
# Fade out the X
steps = 10
for i in range(steps, -1, -1):
fade_color = (int(255 * i / steps), 0, 0)
draw_x_pattern(fade_color)
time.sleep(0.05)
matrix.fill(black)
matrix.write()
digits = f"{score:02}"
# Draw the two digits centered (3x5 font with 1 column space)
matrix.fill(black)
draw_digit(digits[0], 0, 1, red)
draw_digit(digits[1], 5, 1, red)
matrix.write()
time.sleep(1.5)
matrix.fill(black)
matrix.write()
def spiel():
snake = [(4, 4)]
essen = neues_essen(snake)
schwierigkeit = warte_auf_taste()
zeit = SCHWIERIGKEITEN[schwierigkeit - 1]
richtung = "rechts"
while True:
naechste_richtung = neue_richtung(zeit)
if naechste_richtung in RICHTUNGEN and not ist_entgegengesetzt(naechste_richtung, richtung):
richtung = naechste_richtung
dx, dy = RICHTUNGEN[richtung]
head_x, head_y = snake[0]
neuer_kopf = (head_x + dx, head_y + dy)
if (neuer_kopf in snake or
not (0 <= neuer_kopf[0] < 8 and 0 <= neuer_kopf[1] < 8)):
game_over(len(snake) - 1)
break
snake.insert(0, neuer_kopf)
if neuer_kopf == essen:
essen = neues_essen(snake)
else:
snake.pop()
anzeigen(snake, essen)
while True:
spiel()