Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Pygame] Tetris

Le casse tête des rotations !

Sujet résolu
    30 décembre 2010 à 14:50:41

    Bonjour tout le monde,

    Ayant un petit peu de temps libre devant moi (après quelques semaines d'absences) je me suis lancé dans un jeu rétro, le fameux Tetris.
    Le jeu codé à environ 60%, je m'attaque alors aux rotations. Cela fait des heures que je gribouille sur mon papier comment y parvenir; mais sans succès.

    Comment procéder aux rotations quelque soit la forme actuelle (un 'T', un 'Z', un 'L', un ...) ?
    Comment faites-vous ?


    J'avais commencé par prendre l'abscisse de chaque bloc et de le soustraire à lui même; puis son ordonné en l'ajoutant à l'abscisse initial.
    (Soit a et b respectivement l'abscisse et l'ordonné de mon bloc:
    Nouvel abscisse = a - a
    Nouvel ordonné  = b + a
    )
    Sans succès non-plus.

    J'ai dû repenser mon algorithme:

    - Les blocs(4) représentent une forme et ont leur propre coordonnée.
    - Un de ses blocs est un pivot; c'est à dire qu'il ne bouge pas de place lors de la rotation.
    - Calculer les distances qui séparent chaque bloc du bloc-pivot:
    Exemple pour la forme 'L':

    ¤¤  |    BA
    ¤   ->   C
    ¤   |    D


    Coordonnée de chaque bloc: (Bloc B est le bloc pivot [40;-40] soit en dehors de l'écran)
    A-> [60;-40]
    B-> [40;-40]
    C-> [40;-20]
    D-> [40;0]



    Distance séparant les blocs du bloc-pivot:
    A-> [20;0]
    B-> [0;0] Bloc-pivot
    C-> [0;-20]
    D-> [0;-40]

    La forme devient alors:
    ¤¤¤  |  DCB
      ¤ ->    A
         |


    Et ainsi de suite...


    Je vous poste mon code-source au cas-ou.
    En vous remerciant d'avance,
    Realmagma.

    from pygame.locals import *
    import pygame, random, math
    
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-#
    #-*-*- <Les Classes> || Début de <Jeu> -*-*-#
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-#
    
    class Jeu(pygame.sprite.Sprite):
        """Classe <Jeu>"""
        def __init__(self, width = 200, height = 400):
            """Constructeur de la classe:
            - Créer une fenêtre pygame
            - Initialise les variables
    
            """
            pygame.sprite.Sprite.__init__(self)
            pygame.init()
            #Variable du constructeur
            #
            self.width  = width
            self.height = height
            #Variables du jeu
            #
            self.horloge     = pygame.time.Clock()
            self.largeurBloc = 20
            self.l_matrice   = []
            #Screen + Titre
            #
            self.screen = pygame.display.set_mode((self.width, self.height))
            pygame.display.set_caption("My_Tetris")
            #Instantation
            #
            self.bloc   = Bloc()
            #Méthode pour débuter la partie
            #
            self.mainloop()
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def mainloop(self):
            """Boucle principale du jeu.
            - Evènemment Clavier
            - Evènemment Gestion du tps de chute
    
            """
            #Méthodes nécessaires appellées
            #
            self.creerMatrice_vide()
            self.creerGroupe()
            self.creerForme()
            #Variable nécessaire pour la méthode
            #
            continuer = True
            seconde   = 3
            while continuer:
                self.horloge.tick(seconde)
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        pygame.quit()
                        return
                    #Evènemment Clavier
                    #
                    elif event.type == pygame.KEYDOWN:
                        if   event.key == pygame.K_RIGHT:
                            for i in self.g_bloc:
                                i.rect.move_ip(20, 0)
                        elif event.key == pygame.K_LEFT:
                            for i in self.g_bloc:
                                i.rect.move_ip(-20, 0)
                        elif event.key == pygame.K_UP:
                            self.rotation()
                        #On draw & blit & fill + tick pour faire reel
                        #
                        self.drawBlitFill()
                        self.horloge.tick(seconde)
                #On temporise + maj de la map du Tetris
                #
                self.temporisation()
                self.majMap()
                #On blit & Draw & Fill le tout
                #
                self.drawBlitFill()
                #######ESSAI
                #
                if self.bloc.rect[1] >= self.height:
                    for i in self.g_bloc:
                        self.g_bloc.remove(i)
                    self.creerMatrice_vide()
                    self.creerForme()
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def creerMatrice_vide(self):
            """Permet de créer la matrice du terrain de jeu Tetris.
            - Les dimenssions sont fixes.
            - Les bords ont une valeur de 1.
            
            """
            
            largeur   = 200
            #Création des sous-listes
            #20 rangée de 10 cases. (Valeur des cases: 0)
            #
            for i in range(int(self.height/self.largeurBloc)):
                self.l_matrice.append([0] * int(self.width/self.largeurBloc))
    
            #Création des murs G,D,B. Floor()_pour arrondir et
            #-1 pour éviter le débordemment du tableau.
            #
            for i in range(math.floor(self.height/self.largeurBloc)):
                for j in range(math.floor(self.width/self.largeurBloc)):
                    self.l_matrice[i][0]                                          = 2#Gauche
                    self.l_matrice[i][math.floor(self.width/self.largeurBloc)-1]  = 2#Droite
                    self.l_matrice[math.floor(self.height/self.largeurBloc)-1][j] = 2#Bas
            
            
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def creerGroupe(self):
            """Permet de créer un groupe"""
            self.g_bloc = pygame.sprite.Group()
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def drawBlitFill(self):
            """Dessine chaque groupe
            - Blit & Flip & Fill
            """
            self.g_bloc.draw(self.screen)
            pygame.display.flip()
            self.screen.fill((0, 0, 0))
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def temporisation(self):
            """Permet de faire tomber
            les blocs actuels
            """
            for i in self.g_bloc:
                i.rect.move_ip(0, 20)
    
        
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def creerForme(self):
            """Permet de créer des formes différentes
            avec 4 blocs. 
            Les formes seront formées aléatoirement.
            - Forme en l:
            - Forme en T:
            - Forme en L:
            - Forme en Z:
            - Forme carre:
    
            """
            l_choixForme = []
            l_choixForme.append(random.randrange(0, 5))
            #On ajoute 4 blocs
            #
            if l_choixForme[0] == 0: #l
                #0-> 40,-40
                #1-> 40,-60
                #2-> 40,-80
                #3-> 40,-100
                #
                for i in range(4):
                    if i == 0:
                        self.bloc = Bloc()
                        self.g_bloc.add(self.bloc)
                    else:
                        self.bloc = Bloc()
                        self.bloc.rect.topleft = self.bloc.rect[0], self.bloc.rect[1]+i*20
                        self.g_bloc.add(self.bloc)
    
            elif l_choixForme[0] == 1: #T
                #0-> 40,-40
                #1-> 20,-40
                #2-> 40,-20
                #3-> 40,-60
                #
                for i in range(4):
                    self.bloc = Bloc()
                    if   i == 0: pass
                    elif i == 1:
                        self.bloc.rect.topleft = self.bloc.rect[0]-20, self.bloc.rect[1]
                    elif i == 2:
                        self.bloc.rect.topleft = self.bloc.rect[0]+20, self.bloc.rect[1]
                    elif i == 3:
                        self.bloc.rect.topleft = self.bloc.rect[0], self.bloc.rect[1]-20
                    self.g_bloc.add(self.bloc)
    
            elif l_choixForme[0] == 2: #L
                #0-> 40,-40
                #1-> 20,-20
                #2-> 60,-20
                #3-> 80,-60
                #
                for i in range(4):
                    self.bloc = Bloc()
                    if   i == 0: pass
                    elif i == 1:
                        self.bloc.rect.topleft = self.bloc.rect[0], self.bloc.rect[1]+20
                    elif i == 2:
                        self.bloc.rect.topleft = self.bloc.rect[0]+20, self.bloc.rect[1]
                    elif i == 3:
                        self.bloc.rect.topleft = self.bloc.rect[0]+40, self.bloc.rect[1]
                    self.g_bloc.add(self.bloc)
    
            elif l_choixForme[0] == 3: #Z
                #0-> 40,-40
                #1-> 40,-60
                #2-> 60,-40
                #3-> 60,-20
                #
                for i in range(4):
                    self.bloc = Bloc()
                    if   i == 0: pass
                    elif i == 1:
                        self.bloc.rect.topleft = self.bloc.rect[0], self.bloc.rect[1]-20
                    elif i == 2:
                        self.bloc.rect.topleft = self.bloc.rect[0]+20, self.bloc.rect[1]
                    elif i == 3:
                        self.bloc.rect.topleft = self.bloc.rect[0]+20, self.bloc.rect[1]+20
                    self.g_bloc.add(self.bloc)
    
            elif l_choixForme[0] == 4: #Carre
                #0-> 40,-40
                #1-> 60,-40
                #2-> 60,-20
                #3-> 40,-20
                #
                for i in range(4):
                    self.bloc = Bloc()
                    if   i == 0: pass
                    elif i == 1:
                        self.bloc.rect.topleft = self.bloc.rect[0]+20, self.bloc.rect[1]
                    elif i == 2:
                        self.bloc.rect.topleft = self.bloc.rect[0]+20, self.bloc.rect[1]+20
                    elif i == 3:
                        self.bloc.rect.topleft = self.bloc.rect[0], self.bloc.rect[1]+20
                    self.g_bloc.add(self.bloc)
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def majMap(self):
            """Met à jour la liste sur
            la map du Tetris
            """
            #On remet à '0' tout les chiffres de la matrice
            #Sauf les murs '2'
            #
            for i in range(math.floor(self.height/self.largeurBloc)):
                for j in range(math.floor(self.width/self.largeurBloc)):
                    if self.l_matrice[i][j] == 2: pass
                    else:
                        self.l_matrice[i][j] = 0
    
            #La map du Tetris est MAJ
            #Les coord de chaque bloc valent 1 dans la matrice
            #
            for elem in self.g_bloc:
                i = math.floor(elem.rect[0]/20)
                j = math.floor(elem.rect[1]/20)
                #Il ne faut tout de même pas mettre un 1
                #En index out of range
                #
                if i >= 0 and i <= 9 and j >= 0 and j < 20:
                    #On met '1' là ou il ya des blocs
                    self.l_matrice[j][i] = 1
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-* <Jeu>
    
        def rotation(self):
            """Permet la rotation de la forme en
            modifiant les coordonnées de chaque bloc.
            - Un bloc fera office de pivot
                quelque soit la rotation effectuée.
            - Les rotations s'effectuent toujours
                de la même manière.
    
            """
            #c = 0
            #for i in self.g_bloc:
            #    a = i.rect[0]
            #    b = i.rect[1]
            #    print("avant-> a:", i.rect[0], "n°", c)
                
                
            #    i.rect[0] = b-a
            #    i.rect[1] =  a+ a
            #    print("apres-> a:", i.rect[0], "n°", c)
            #    c+=1
    
    
            c = 0
            for i in self.g_bloc:
                #On garde les coordonnées du bloc pivot
                #
                if c == 0:
                    a = i.rect[0]
                    b = i.rect[1]
                #Sert pour les autres bloc
                #
                d = i.rect[0]
                e = i.rect[1]
                #Nouvelles coordonnées
                #
                i.rect[0] = d+a-e 
                i.rect[1] = a+b-d-20
                    
                c+=1
    
            #Prendre coord du pivot, puis bouger les autre par rapport a celui-ci
                
                    
                
            
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-#
    #-*-*- <Les Classes> || Début de <Bloc> -*-*#
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-#
    
    class Bloc(pygame.sprite.Sprite):
        """Classe <Bloc>"""
        def __init__(self):
            """Constructeur de la classe <Bloc>.
            - Initialise les images
            - Donne une surface rectangle
    
            """
            pygame.sprite.Sprite.__init__(self)
            #Chargement de l'image
            #
            self.bloc  = pygame.image.load("bloc3.PNG")
            #Image actuelle
            #
            self.image = self.bloc
            self.rect  = self.image.get_rect()
            self.rect.topleft = (40, -40)
    
    
    
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-#
    #-*-*- <Les Classes> || Début de <Mur> -*-*-#
    #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-#
    
    class Mur(pygame.sprite.Sprite):
        """Classe <Mur>"""
        def __init__(self):
            """Constructeur de la classe <Mur>.
            - Initialise les images
            - Donne une surface rectangle
    
            """
            pygame.sprite.Sprite.__init__(self)
            #Chargement de l'image
            #
            self.mur  = pygame.image.load("bloc2.PNG")
            #Image actuelle
            #
            self.image = self.mur
            self.rect  = self.image.get_rect()
            
            
    
    
                  
    #l_posCellule = []
    #matrice = []
    #for i in range(10):
    #    matrice.append([0] * 3)
    
    #Création de la pièce
    #matrice[0][0] = 1
    #matrice[0][1] = 1
    #matrice[0][2] = 1
    #matrice[1][0] = 1
    
            
    #for i in range(10):
    #    for j in range(3):
            #On récupère les coord des pièces
    #        if matrice[i][j] == 1:
    #            l_posCellule.append([i, j])
    #            matrice[i][j] = 0
    
    
    
            
    
    
    if __name__ == "__main__":
        partie = Jeu()
        partie.mainloop()
    
    • Partager sur Facebook
    • Partager sur Twitter
      30 décembre 2010 à 19:34:49

      Ce petit site parle de cet algorythme, j'espère qu'il t'aidera, bonne chance :)

      Edit: J'avais oublié le lien :-°

      http://fr.w3support.net/index.php?db=so&id=233850
      • Partager sur Facebook
      • Partager sur Twitter
        30 décembre 2010 à 20:17:44

        Merci beaucoup.
        Les rotations s'effectuent, des murs ont été crées pour délimiter le terrain de jeu.

        Je vais m'attaquer aux gestions de collisions ainsi une suppression de ligne si elle est complète + gestion du score.
        Je finirai ensuite par créer un jolie rendu et enfin par optimiser mon code-source (Il a déjà bien changé depuis la dernière fois :) )

        Merci,
        Realmagma.
        • Partager sur Facebook
        • Partager sur Twitter

        [Pygame] Tetris

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown