====== Tetris auf der OxoCard ====== Erläuterungen zum Code gibt es als Videos: * [[https://fginfo.ksbg.ch/~ivo/videos/informatik/python/oxocard-tetris-uebersicht.mp4|Übersicht über den Tetris-Code]] (und für Datenspender auf [[https://web.microsoftstream.com/video/53283307-05fb-4568-b6ae-9c0af3a51e18|Stream]]) * [[https://fginfo.ksbg.ch/~ivo/videos/informatik/python/oxocard-tetris-variable-feld.mp4|Erklärungen zur Variable]] ''tetris['feld']'' (und für Datenspender auf [[https://web.microsoftstream.com/video/de88ae07-5296-46ad-adec-eb8bbce41706|Stream]]) * [[https://fginfo.ksbg.ch/~ivo/videos/informatik/python/oxocard-tetris-stein-manipulation.mp4|Erklärungen zur Datenstruktur und Manipulation der Steine]] (und für Datenspender auf [[https://web.microsoftstream.com/video/d5095d75-191c-4f27-95e2-b7b1a4d538a6|Stream]]) from oxocard import * from ivobuttons import * from random import randrange # Funktion randrange importieren ivobuttons.delay=300 # Tasten nach 300ms repetieren repetieren beginnen ivobuttons.repeat_delay=100 # Tasten danach 10x pro Sekunde repetieren # Gamestate als Dictionary, d.h. wie eine Liste aber mit Namen als Indizes tetris = { "feld": [[False for y in range(8)] for x in range(8)], # Pixel belegt oder nicht (wenn belegt, dann Farbe) "steine": list(map(lambda x:list(map(lambda y: [y%4,y//4],x)), [(0,1,2,3),(0,1,2,5), (0,1,4,5), (0,1,5,6), (4,5,1,2), (0,1,2,6), (4,0,1,2)])), "farben": [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255), (0,255,255),(255,255,255)], "stein": None, # Positionen der Steinpixel "farbe": None, "empty" : (10,10,10), # Hintergrundfarbe, damit das Spielfeld sichtbar ist. "x": None, # Untere linke Ecke der Boundingbox des Steins "y": None, # Untere linke Ecke der Boundingbox des Steins "last": 0, # Zeit bis der Stein weiter fällt. "score": 0, } # Ergibt True, wenn der Stein platziert werden kann, # False sonst. def platzierbar(stein,x,y): global tetris return all((pt[0]+x>=0 and pt[0]+x<=7 and pt[1]+y<=7 and (pt[1]+y<0 or tetris['feld'][pt[0]+x][pt[1]+y]==False)) for pt in stein) # Generiert einen neuen Stein und gibt # True zurück, wenn das möglich ist, und sonst # False, wenn der Stein nicht mehr platziert werden kann. def neuerStein(): global tetris # Zufälligen Stein kopieren stein = randrange(len(tetris["steine"])) tetris["stein"] = [[pt[0], pt[1]] for pt in tetris["steine"][stein]] tetris["farbe"] = tetris["farben"][stein] tetris["x"]=3 # Koordinaten vom Stein tetris["y"]=-max(pt[1] for pt in tetris["stein"]) tetris["last"] = getms() # Zeit der Letzten Aktion, damit der Stein selber fällt tetris['score']+=1 print("Score %d" % tetris['score']) return platzierbar(tetris["stein"], tetris["x"], tetris["y"]) # Generiert ein neues Array mit Koordinaten des gedrehten Steins # Die richtung ist +1 oder -1 def drehen(richtung): global tetris # Gedrehte Koordinaten res = [[pt[1]*richtung,-pt[0]*richtung] for pt in tetris["stein"]] # Untere linke Ecke mins = [min([pt[0] for pt in res]), max([pt[1] for pt in res])] for pt in res: for i in range(2): pt[i]-=mins[i] return res # Aktuellen Stein zeichnen (evtl. mit Farbe) def steinZeichnen(farbe=None): global tetris if farbe==None: farbe = tetris['farbe'] for pt in tetris['stein']: if (pt[1]+tetris['y'] >=0): if farbe==BLACK: black(pt[0]+tetris['x'], pt[1]+tetris['y']) else: fastDot(pt[0]+tetris['x'], pt[1]+tetris['y'], farbe) fastRepaint() # y ist ein Array mit True/False, welche Linien zu blinken sind def blinkLines(y): for i in range(5): for farbe in (WHITE, BLACK): for yy in range(8): if y[yy]: for xx in range(8): fastDot(xx,yy, farbe) fastRepaint() sleep(0.1) # Lässt Linien verschwinden, wobei y ein Array mit True/False für jede Linie ist. def removeLines(y): global tetris count = 0 for yy in range(8): if y[yy]: count+=1 for yyy in range(yy,-1,-1): for x in range(8): f = BLACK if yyy>0: tetris['feld'][x][yyy] = tetris['feld'][x][yyy-1] else: tetris['feld'][x][yyy] = False if tetris['feld'][x][yyy]: fastDot(x,yyy,tetris['feld'][x][yyy]) else: black(x,yyy); fastRepaint() sleep(0.1) tetris['score']+= [0,5,20,100,500][count] print("Score %d" % tetris['score']) # Überprüft, ob volle Zeilen da sind und löscht diese def checkLines(): global tetris # Array mit True, False, für volle Zeilen True y = [all(tetris['feld'][x][y] for x in range(8)) for y in range(8)] # Volle Zeilen? if any(y): blinkLines(y) removeLines(y) # Stein runter, evtl. Linien löschen, neuer Stein generieren # Liefert False, wenn das Spiel weiter geht # True, wenn GameOver ist. def steinDown(): global tetris tetris['last'] = zeit if platzierbar(tetris['stein'], tetris['x'], tetris['y']+1): steinZeichnen(BLACK) tetris['y']+=1 steinZeichnen() return False else: # Stein definitiv platzieren: for pt in tetris['stein']: if (pt[1]+tetris['y']>=0): tetris['feld'][pt[0]+tetris['x']][pt[1]+tetris['y']] = tetris['farbe'] checkLines() return not neuerStein() # Richtung ist +1 oder -1 def steinMove(richtung): global tetris if platzierbar(tetris['stein'], tetris['x']+richtung, tetris['y']): steinZeichnen(BLACK) tetris['x']+=richtung steinZeichnen() # Richtung ist +1 oder -1 def steinRotate(richtung): global tetris gedreht = drehen(richtung) if platzierbar(gedreht, tetris['x'], tetris['y']): steinZeichnen(BLACK) tetris['stein']=gedreht steinZeichnen() def black(x,y): fastDot(x,y, (4,4,4)); def init(): for x in range(8): for y in range(8): black(x,y) neuerStein(); steinZeichnen(); bigTextScroll(" Oxo Tetris ", (10,40,200), BLACK) init() ############# # Game Loop # ############# gameOver = False while not gameOver: zeit = getms() s = ivobuttons.states() if zeit-tetris['last']>800 or s & IVO_R3: gameOver = steinDown(); if s & IVO_L2: steinMove(-1) if s & IVO_R2: steinMove(1) if s & IVO_R1: steinRotate(1) if s & IVO_L1: steinRotate(-1) # Game Over print("Game over") while True: bigTextScroll((" %d " % tetris['score']), (100,0,0), BLACK) ===== Highscores auf dem Web ===== Was folgt sind Notizen, um von der OxoCard die Highscores auf dem Web zu publizieren. from tcpcom import * # See dcoumentation directly in the code of the OxoCard modules files Wlan.connect("stopbuepf", "stopbuepf") client = HTTPClient() # Pass True for debugging... client._isSSL=True if client.connect("tech-lab.ch", 443): # Host is used in HTTP-Query response = client.sendPostRequest("/scores/index.php", "name="+HTTPClient.toUrl("Hase")+"&score=123") print(response) client.closeConnection()