Yet another Tetris, but with 3 modes : classic extended and 2 players 1P : left & right to move aside, down to go down , Up to rotate 2P : 3 & minus to move aside, Ans to go down, + to rotate
====================================================
Encore un autre tetris, mais avec 3 modes : le classique, une version étendue où la grille passe à 21 colonnes de large et surtout un mode 2 players en versus (chaque ligne complétée apparaît chez l’adversaire)
pavé directionnel pour le P1 (haut pour tourner)
3,+,-,Ans pour le P2
from math import * from kandinsky import * from ion import * from time import * from random import randint couleurs_defaut = ( (64, 64, 64), (0, 255, 255), (255, 255, 0), (255, 0, 255), (255, 128, 0), (0, 0, 255), (255, 0, 0), (0, 255, 0), (128, 128, 128), ) class Grille: def __init__( self, pos_x=0, pos_y=0, lignes=22, colonnes=10, unite=10, coul_ligne=(64, 64, 0), couleurs=couleurs_defaut, aleatoire=False, ): self.pos_x = pos_x self.pos_y = pos_y self.couleurs = couleurs self.lignes = lignes self.colonnes = colonnes self.unite = unite self.coul_ligne = self.couleurs[-1] if aleatoire: self.contenu = [ [randint(0, len(self.couleurs) - 1) for i in range(self.colonnes)] for j in range(self.lignes) ] else: self.contenu = [ [0 for i in range(self.colonnes)] for j in range(self.lignes) ] def print(self): # fill_rect(0,0,320,222,(0,0,0)) for i in range(self.lignes): for j in range(self.colonnes): fill_rect( self.pos_x + j * self.unite, self.pos_y + i * self.unite, self.unite, self.unite, self.coul_ligne, ) fill_rect( self.pos_x + j * self.unite + 1, self.pos_y + i * self.unite + 1, self.unite - 2, self.unite - 2, self.couleurs[self.contenu[i][j]], ) def new_mos(self): # crée une mosaïque aléatoire self.contenu = [ [randint(0, len(self.couleurs) - 1) for i in range(self.colonnes)] for j in range(self.lignes) ] self.print() def is_complete(self, ligne): # regarde si la ligne est complète for i in range(self.colonnes): if self.contenu[ligne][i] == 0: return False return True def rem( self, ligne ): # efface la ligne indiquée puis rajoute une ligne a début (tout en haut) del self.contenu[ligne] self.contenu.insert(0, [0 for i in range(self.colonnes)]) class Piece: briques = [0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0, 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0, 0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0, 0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0, 0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0, 0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,1,1,0,0,0,0] # couleurs=((0,0,0),(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255),(255,128,0),(128,128,128)) def __init__(self, race, grille, pos=(3, -3)): self.actuelle = [ [self.briques[race * 16 + 4 * i + j] for j in range(4)] for i in range(4) ] self.future = [i for i in self.actuelle] self.grille = grille self.pos = pos self.race = race self.couleur = self.grille.couleurs[race + 1] def rotate(self): self.future = rotate(self.actuelle) self.efface() for i in range(4): for j in range(4): if self.future[i][j]: if ( j + self.pos[0] < 0 or j + self.pos[0] >= self.grille.colonnes or i + self.pos[1] >= self.grille.lignes ): self.print() return False elif self.grille.contenu[i + self.pos[1]][j + self.pos[0]] != 0: self.print() return False self.actuelle = [[self.future[i][j] for j in range(4)] for i in range(4)] self.print() return True def anti_rotate(self): self.future = anti_rotate(self.actuelle) self.efface() for i in range(4): for j in range(4): if self.future[i][j]: if ( j + self.pos[0] < 0 or j + self.pos[0] >= self.grille.colonnes or i + self.pos[1] >= self.grille.lignes ): self.print() return False elif self.grille.contenu[i + self.pos[1]][j + self.pos[0]] != 0: self.print() return False self.actuelle = [[self.future[i][j] for j in range(4)] for i in range(4)] self.print() return True def bas(self): self.efface() for i in range(4): for j in range(4): if self.actuelle[i][j]: if ( 0 <= self.pos[1] + i + 1 < self.grille.lignes and 0 <= self.pos[0] + j < self.grille.colonnes ): if ( self.grille.contenu[self.pos[1] + i + 1][self.pos[0] + j] != 0 ): self.print() return False elif self.pos[1] + i + 1 == self.grille.lignes: self.print() return False self.pos = (self.pos[0], self.pos[1] + 1) self.print() return True def gauche(self): self.efface() for i in range(4): for j in range(4): if self.actuelle[i][j]: if ( self.pos[0] + j - 1 < 0 or self.pos[0] + j - 1 >= self.grille.colonnes ): self.print() return False else: if self.pos[1] + i < 0: pass elif ( self.grille.contenu[self.pos[1] + i][self.pos[0] + j - 1] != 0 ): self.print() return False self.pos = (self.pos[0] - 1, self.pos[1]) self.print() return True def droite(self): self.efface() for i in range(4): for j in range(4): if self.actuelle[i][j]: if ( self.pos[0] + j + 1 < 0 or self.pos[0] + j + 1 >= self.grille.colonnes ): self.print() return False else: if self.pos[1] + i < 0: pass elif ( self.grille.contenu[self.pos[1] + i][self.pos[0] + j + 1] != 0 ): self.print() return False self.pos = (self.pos[0] + 1, self.pos[1]) self.print() return True def colle(self): self.efface() for i in range(4): for j in range(4): try: if ( self.pos[0] + j < self.grille.colonnes and self.pos[0] + j >= 0 and self.pos[1] + i < self.grille.lignes and self.pos[1] + i >= 0 and self.actuelle[i][j] ): self.grille.contenu[self.pos[1] + i][self.pos[0] + j] = ( self.race + 1 ) except: pass self.grille.print() def print(self): for i in range(4): for j in range(4): if self.actuelle[i][j]: fill_rect( self.grille.pos_x + (j + self.pos[0]) * self.grille.unite, self.grille.pos_y + (i + self.pos[1]) * self.grille.unite, self.grille.unite, self.grille.unite, self.couleur, ) def efface(self): for i in range(4): for j in range(4): if self.actuelle[i][j]: fill_rect( self.grille.pos_x + (j + self.pos[0]) * self.grille.unite, self.grille.pos_y + (i + self.pos[1]) * self.grille.unite, self.grille.unite, self.grille.unite, self.grille.coul_ligne, ) fill_rect( self.grille.pos_x + (j + self.pos[0]) * self.grille.unite + 1, self.grille.pos_y + (i + self.pos[1]) * self.grille.unite + 1, self.grille.unite - 2, self.grille.unite - 2, self.grille.couleurs[0], ) def efface_tot(self): fill_rect( self.grille.pos_x + self.pos[0] * self.grille.unite, self.grille.pos_y + self.pos[1] * self.grille.unite, 4 * self.grille.unite, 4 * self.grille.unite, self.grille.couleurs[0], ) class Jeu: def __init__(self, level=0, score=0, couleurs=couleurs_defaut): self.grille = Grille() self.score = score self.level = level self.etat = 0 self.couleurs = couleurs def play(self, mode=0): fill_rect(0, 0, 320, 240, self.couleurs[0]) if mode == 0: self.grille = Grille() texte("TETRIS", 110, 10, 5, self.couleurs[-1]) texte("Next", 110, 80, 3, self.couleurs[-1]) texte("Level", 110, 150, 2, self.couleurs[-1]) texte(str(self.level), 178, 150, 2, self.couleurs[-1]) texte("Score", 110, 180, 2, self.couleurs[-1]) texte(str(self.score), 178, 180, 2, self.couleurs[-1]) self.pos_suivante = (20, 7) elif mode == 1: self.grille = Grille(0, 0, 22, 20) texte("TETRIS", 210, 10, 3, self.couleurs[-1]) texte("Next", 240, 40, 2, self.couleurs[-1]) texte("Level", 240, 100, 2, self.couleurs[-1]) texte(str(self.level), 240, 120, 2, self.couleurs[-1]) texte("Score:", 240, 170, 2, self.couleurs[-1]) texte(str(self.score), 240, 190, 2, self.couleurs[-1]) self.pos_suivante = (24, 6) else: # mode==2, mode 2 joueurs self.grille = Grille() self.grille2 = Grille(220, 0, 22, 10) self.pos_suivante = (11, 0) choix = randint(0, 6) self.piece2 = Piece(choix, self.grille2) choix = randint(0, 6) self.suivante2 = Piece(choix, self.grille2, (-6, 16)) self.suivante2.efface_tot() self.suivante2.print() self.grille2.print() new2 = True lignes_tot = 0 choix = randint(0, 6) self.piece = Piece(choix, self.grille) new = True choix = randint(0, 6) self.suivante = Piece(choix, self.grille, self.pos_suivante) self.suivante.efface_tot() self.suivante.print() self.grille.print() temps = monotonic() while True: # delta est le temps entre 2 avancées successives # semble correspondre au timing original if self.level < 9: delta = -0.0742 * self.level + 0.899 else: delta = -0.012 + 0.278 while monotonic() - temps < delta: deplacement = False if keydown(KEY_LEFT): deplacement = deplacement or self.piece.gauche() if keydown(KEY_RIGHT): deplacement = deplacement or self.piece.droite() if keydown(KEY_DOWN): descend = self.piece.bas() deplacement = deplacement or descend if descend: new = False if keydown(KEY_UP): deplacement = deplacement or self.piece.rotate() if mode == 2: if keydown(KEY_THREE): deplacement = deplacement or self.piece2.gauche() if keydown(KEY_MINUS): deplacement = deplacement or self.piece2.droite() if keydown(KEY_ANS): descend = self.piece2.bas() deplacement = deplacement or descend if descend: new2 = False if keydown(KEY_PLUS): deplacement = deplacement or self.piece2.rotate() if deplacement: if self.level < 5: sleep(0.05) elif self.level < 10: sleep(0.04) elif self.level < 15: sleep(0.03) else: sleep(0.02) test = self.piece.bas() temps = monotonic() if (not test) and new: break if new: new = False if not test: self.piece.colle() self.score += 1 nb_lignes = 0 for i in range(self.grille.lignes): if self.grille.is_complete(i): nb_lignes += 1 self.grille.rem(i) self.grille.print() if nb_lignes == 1: self.score += 40 * (1 + self.level) elif nb_lignes == 2: self.score += 100 * (1 + self.level) elif nb_lignes == 3: self.score += 300 * (1 + self.level) elif nb_lignes == 4: self.score += 1200 * (1 + self.level) lignes_tot += nb_lignes if lignes_tot >= self.level * 10 + 10: self.level += 1 if mode == 2: # on ajoute les lignes au joueur 2 for i in range(nb_lignes): self.grille2.contenu.append( [randint(0, 7) for j in range(self.grille2.colonnes)] ) del self.grille2.contenu[0] self.grille2.print() self.piece = Piece(self.suivante.race, self.grille) choix = randint(0, 6) new = True self.suivante.efface_tot() if mode == 0: fill_rect(178, 150, 100, 60, self.couleurs[0]) texte(str(self.level), 178, 150, 2, self.couleurs[-1]) texte(str(self.score), 178, 180, 2, self.couleurs[-1]) self.suivante = Piece(choix, self.grille, (20, 7)) elif mode == 1: fill_rect(240, 130, 100, 30, self.couleurs[0]) texte(str(self.level), 240, 120, 2, self.couleurs[-1]) fill_rect(240, 190, 100, 30, self.couleurs[0]) texte(str(self.score), 240, 190, 2, self.couleurs[-1]) self.suivante = Piece(choix, self.grille, (24, 6)) else: self.suivante = Piece(choix, self.grille, (11, 0)) self.suivante.print() if mode == 2: if new2: new2 = False test2 = self.piece2.bas() if (not test2) and new2: break if not test2: self.piece2.colle() self.score += 1 nb_lignes = 0 for i in range(self.grille2.lignes): if self.grille2.is_complete(i): nb_lignes += 1 self.grille2.rem(i) self.grille2.print() if nb_lignes == 1: self.score += 40 * (1 + self.level) elif nb_lignes == 2: self.score += 100 * (1 + self.level) elif nb_lignes == 3: self.score += 300 * (1 + self.level) elif nb_lignes == 4: self.score += 1200 * (1 + self.level) lignes_tot += nb_lignes if lignes_tot >= self.level * 10 + 10: self.level += 1 # on ajoute les lignes au joueur 1 for i in range(nb_lignes): self.grille.contenu.append( [randint(0, 7) for j in range(self.grille.colonnes)] ) del self.grille.contenu[0] self.grille.print() self.piece2 = Piece(self.suivante2.race, self.grille2) choix = randint(0, 6) new2 = True self.suivante2.efface_tot() self.suivante2 = Piece(choix, self.grille2, (-6, 16)) self.suivante2.print() self.GameOver() def GameOver(self): Grille(0, 0, 22, 32, 10, (64, 64, 0), couleurs_defaut, True).print() texte_bg("GAME", 90, 10, 140, (255, 255, 255), 5, (64, 64, 64), 10) texte_bg("OVER", 90, 70, 140, (255, 255, 255), 5, (64, 64, 64), 10) texte_bg("Level", 90, 150, 68, (255, 255, 255), 2, (64, 64, 64), 4) texte_bg(str(self.level), 158, 150, 68, (255, 255, 255), 2, (64, 64, 64), 4) texte_bg("Score", 90, 180, 68, (255, 255, 255), 2, (64, 64, 64), 4) texte_bg(str(self.score), 158, 180, 68, (255, 255, 255), 2, (64, 64, 64), 4) def Intro(self): Grille(0, 0, 22, 32, 10, (64, 64, 0), couleurs_defaut, True).print() texte_bg("TETRIS", 60, 0, 200, (255, 255, 255), 5, (64, 64, 64), 10) texte_bg("Classic", 70, 80, 180, (255, 255, 255), 3, (64, 64, 64), 10) texte_bg("Extended", 70, 130, 180, (255, 255, 255), 3, (64, 64, 64), 10) texte_bg("2 Players", 70, 180, 180, (255, 255, 255), 3, (64, 64, 64), 10) cadre = Rectangle_Clignotant(70, 80, 180, 44, 5) while not keydown(KEY_OK): cadre.print() if keydown(KEY_DOWN): cadre.efface() cadre.y = 80 + (cadre.y - 80 + 50) % 150 print(str(cadre.y)) elif keydown(KEY_UP): cadre.efface() cadre.y = 80 + (cadre.y - 80 - 50) % 150 print(str(cadre.y)) sleep(0.2) print((cadre.y - 80) // 50) self.play((cadre.y - 80) // 50) class Rectangle_Clignotant: def __init__( self, x, y, width, height, thickness=10, couleurs=couleurs_defaut[0:-1], bg_color=(couleurs_defaut[0]), ): self.x, self.y, self.width, self.height, self.thickness, self.couleurs, self.bg_color = ( x, y, width, height, thickness, couleurs, bg_color, ) self.choix_coul = 0 def print(self): fill_rect( self.x, self.y, self.width, self.thickness, self.couleurs[self.choix_coul] ) fill_rect( self.x, self.y + self.height - self.thickness, self.width, self.thickness, self.couleurs[self.choix_coul], ) fill_rect( self.x, self.y, self.thickness, self.height, self.couleurs[self.choix_coul] ) fill_rect( self.x + self.width - self.thickness, self.y, self.thickness, self.height, self.couleurs[self.choix_coul], ) self.choix_coul = (self.choix_coul + 1) % len(self.couleurs) def efface(self): fill_rect(self.x, self.y, self.width, self.thickness, self.bg_color) fill_rect( self.x, self.y + self.height - self.thickness, self.width, self.thickness, self.bg_color, ) fill_rect(self.x, self.y, self.thickness, self.height, self.bg_color) fill_rect( self.x + self.width - self.thickness, self.y, self.thickness, self.height, self.bg_color, ) def rotate(matrice): return [ [matrice[j][-1 - i] for j in range(len(matrice[i]))] for i in range(len(matrice)) ] def anti_rotate(matrice): return [ [matrice[-1 - j][i] for j in range(len(matrice[i]))] for i in range(len(matrice)) ] lettres = { "A": "0111010001100011000111111100011000100000", "B": "1111010001100011111010001100011111000000", "C": "0111010001100001000010000100010111000000", "D": "1111010010100011000110001100101111000000", "E": "1111110000100001110010000100001111100000", "F": "1111110000100001110010000100001000000000", "G": "0111110000100001001110001100010111100000", "H": "1000110001100011111110001100011000100000", "I": "0111000100001000010000100001000111000000", "J": "0111100010000100001000010100100110000000", "K": "1000110010101001110010010100101000100000", "L": "0100001000010000100001000010000111100000", "M": "1000111011101011000110001100011000100000", "N": "1000111001101011001110001100011000100000", "O": "0111010001100011000110001100010111000000", "P": "1111010001100011111010000100001000000000", "Q": "0111010001100011000110101100100110100000", "R": "1111010001100011111010010100011000100000", "S": "0111010001100000111000001100010111000000", "T": "1111100100001000010000100001000010000000", "U": "1000110001100011000110001100010111000000", "V": "1000110001100011000101010010100010000000", "W": "1000110001100011000110101110111000100000", "X": "1000110001010100010001010100011000100000", "Y": "1000110001100010101000100001000010000000", "Z": "1111100001000100010001000100001111100000", "a": "0000001110000010111110001100010111100000", "b": "1000010000111101000110001100011111000000", "c": "0000000000011101000110000100000111100000", "d": "0000100001011111000110001100010111100000", "e": "0000001110100011111110000100000111100000", "f": "0000000111010000100011110010000100000000", "g": "0000001111100011000110001011110000101110", "h": "1000010000100001011011001100011000100000", "i": "0000000100000000110000100001000111000000", "j": "0000000100000000010000100001000010011000", "k": "0000001000010000100101010011010100100000", "l": "0100001000010000100001000001000001100000", "m": "0000000000010101010110101101011010100000", "n": "0000000000101101100110001100011000100000", "o": "0000000000011101000110001100010111000000", "p": "0000000110010010100101110010000100001000", "q": "0000000000001100100101001001110000100001", "r": "0000000000001110110001000010000100000000", "s": "0000000000001110100000111000010111000000", "t": "0000001000011100100001000010000011000000", "u": "0000000000000001000110001100110110100000", "v": "0000000000000001000110001010100010000000", "w": "0000000000000001000110101101010101000000", "x": "0000010001010100010000100010101000100000", "y": "0000001001010010100100110000100110000010", "z": "0000000000011110000100110010000111100000", "0": "0111010001101011010110101100010111000000", "1": "0010011100001000010000100001001111100000", "2": "0111010001000010001000100010011111100000", "3": "0111010001000010011000001100010111000000", "4": "0010001010100101001011111000100001000000", "5": "1111110000111100000100001100011111000000", "6": "0111010001100001111010001100010111000000", "7": "1111110001000010001000100010000100000000", "8": "0111010001100010111010001100010111000000", "9": "0111010001100010111100001010010011000000", " ": "0000000000000000000000000000000000000000", ".": "0000000000000000000000000001100011000000", ",": "0000000000000000000000110001100001000100", ":": "0000000000000000010000000000000010000000", } for i in lettres.keys(): conversion = [] for j in lettres[i]: if j == "0": conversion.append(False) else: conversion.append(True) lettres[i] = conversion def main(): posx, posy = 0, 0 dispos = sorted(list(lettres.keys())) for k in range(1, 4): for i in range(len(dispos)): for j in range(len(lettres[dispos[i]])): x = posx + (k * 6 * i) % 320 + k * (j % 5) y = posy + 9 * k * ((k * 9 * i) // 320) + k * (j // 5) if lettres[dispos[i]][j]: for l in range(k): for m in range(k): set_pixel(x + l, y + m, (0, 0, 0)) posy = y + 9 * k def texte(chaine, posx=0, posy=0, taille=1, color=(0, 0, 0)): for i in range(len(chaine)): carac = chaine[i] if not carac in lettres.keys(): carac = " " for j in range(len(lettres[carac])): x = posx + (taille * 6 * i) % 320 + taille * (j % 5) y = posy + taille * (j // 5) if lettres[carac][j]: for k in range(taille): for l in range(taille): set_pixel(x + k, y + l, color) def texte_bg( chaine, posx=0, posy=0, width=320, color=(0, 0, 0), taille=1, bg_color=(255, 255, 255), padding=10, ): fill_rect( posx, posy, width, 9 * (taille + (taille * 6 * len(chaine)) // width) + 2 * padding, bg_color, ) texte(chaine, posx + padding, posy + padding, taille, color) a = Jeu() a.Intro()