from machine import Pin, I2C
import ssd1306
import random
import time
WIDTH = 10
HEIGHT = 16
BLOCK = 4
SPERRZEIT_MS = 50
letzter_ms_left = 1
letzter_ms_right = 1 #für die knöpfe damit sie nicht zu schnell ausgeführt wird
letzter_ms_rotate_btn = 1
letzter_ms_down = 1
# OLED
i2c = I2C(0, scl=Pin(1), sda=Pin(0))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
board = [[0]*WIDTH for _ in range(HEIGHT)]#zeigt bildschirm an und malt.ohne wird nichts angezeigt
score = 0
# Buttons
left = Pin(2, Pin.IN, Pin.PULL_DOWN)
right = Pin(3, Pin.IN, Pin.PULL_DOWN) #pins und wie sie definiert sind
rotate_btn = Pin(4, Pin.IN, Pin.PULL_DOWN)
down = Pin(5, Pin.IN, Pin.PULL_DOWN)
# Tetris Steine
pieces = [
[[1,1,1,1]],
[[1,1],[1,1]], #tetris steine und wie sie gebaut sind
[[0,1,0],[1,1,1]],
[[1,0,0],[1,1,1]],
[[0,0,1],[1,1,1]]
]
def rotate(p):
return [list(row) for row in zip(*p[::-1])]#drehung des pieces um 90 grad
def can_move(p,x,y): #Prüft, ob sich ein Piece an Position (x, y) befinden darf
for py in range(len(p)): #geht jedes Feld des Pieces durch
for px in range(len(p[py])):
if p[py][px]: #bei existierendem block wird die position berechnet
nx = x + px #
ny = y + py #
if nx < 0 or nx >= WIDTH or ny >= HEIGHT: #kollisionen prüfen
return False #
if ny >= 0 and board[ny][nx]: #
return False #
return True #
def merge(p,x,y): #fixiert ein piece im spielfeld
for py in range(len(p)):
for px in range(len(p[py])):
if p[py][px]:
board[y+py][x+px] = 1 #blöcke werden fest ins board geschrieben
def clear_lines(): #Entfernt volle Reihen
global score
new_board = [row for row in board if not all(row)] #prüft, ob die Reihe komplett voll ist
lines = HEIGHT - len(new_board)
for _ in range(lines): #So „rutscht“ alles nach unten
new_board.insert(0,[0]*WIDTH) #
score += lines * 10 #10 Punkte pro Linie
return new_board
def draw_block(x,y): #Zeichnet einen einzelnen Block auf dein Display.
oled.fill_rect(x*BLOCK,y*BLOCK,BLOCK,BLOCK,1) #
def draw(piece, px, py):
oled.fill(0) #spielfeld säubern
# feste Blöcke
for y in range(HEIGHT): #jede position im spielfeld wird durchgegangen
for x in range(WIDTH): #
if board[y][x]: #
draw_block(x,y) #Alle bereits „festen“ Blöcke werden angezeigt
# aktueller fallender Stein
for y in range(len(piece)): #fallende steine werden gezeichnet
for x in range(len(piece[y])): #
if piece[y][x]: #
draw_block(px + x, py + y) #Der Stein „schwebt“ über dem Spielfeld und fällt
oled.text("Score:"+str(score),45,0)
oled.line(40, 0, 40, 200, 1) #
oled.line(0, 0, 0, 200, 1) #
oled.line(0, 63, 40, 63, 1) #linien werden gezeichnet und angezeigt
oled.show() #
piece = random.choice(pieces) #zufälliger stein wird ausgewählt
x = WIDTH//2 #erscheint ungefähr in der mitte
y = 0 #ganz oben
while True: #unendliche schleife
if left.value() and can_move(piece,x-1,y): #bewegung nach links und rechts
x -= 1 #
if right.value() and can_move(piece,x+1,y): #
x += 1 #
if rotate_btn.value(): #button gedrückt?
r = rotate(piece) #test rotation
if can_move(r,x,y): #prüfen ob rotation gültig ist
piece = r #
speed = 0.1 if down.value() else 0.5 #fallgeschwindigkwit
if can_move(piece,x,y+1): #automatisches fallen
y += 1 #
else:
merge(piece,x,y) #Piece wird im Spielfeld fixiert
board = clear_lines() #Volle Reihen verschwinden + Score steigt
piece = random.choice(pieces) #Nächster Stein kommt rein(random)
x = WIDTH//2 #in der mitte(ungefähr)
y = 0 #ganz oben
draw(piece,x,y) #aktueller stein wird gezeichnet
time.sleep(speed) #Steuert die Geschwindigkeit des Spiels