Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de boucle d'arrière plan PyQt5

    24 septembre 2022 à 19:07:18

    Bonjour, je suis en train de créer le jeux snake et j'utilise pour cela la bibliothèque PyQt5. J'y arrive globalement bien, cependant, je rencontre un problème assez important dans ma boucle principale. Le jeux est construit de la sorte : je créer une grille que je remplie de QWidget de couleur noir. Puis je change la couleur des cases pour créer le serpent. Pour que tous fonctionne, je dois créer une fonction qui update la grille. Elle marche sans problème car son fonctionnement est relativement simple. Ainsi, lorsque je fais tourné le jeux en "manuelle", je ne rencontre aucun problème, par contre quand je fais tourné le jeux dans ma boucle principale, plus rien ne fonctionne. Je ne comprend vraiment pas pourquoi car ce sont exactement les même fonction qui sont appelés dans les deux cas. Cela devrait me donner le même résultat et pourtant non.

    Je vais mettre les deux version, celle que j'appelle "manuelle", c'est à dire que les évènement se déclenche lors de l'appuie des touches puis la version normal, c'est à dire avec la boucle principale. Le jeux n'est pas finis, mais sans résoudre ce problème, je n'aboutirais pas.

    Voici donc la version "manuelle", c'est à dire de test:

    from PyQt5.QtWidgets import QWidget, QGridLayout, QApplication
    from PyQt5.QtCore import Qt
    import sys
    from main import Snake
    import time
    from threading import Thread
    
    app = QApplication(sys.argv)
    
    class SnakeGame(QWidget):
        """Cette classe est la partie graphique du
        jeu snake"""
    
        def __init__(self):
            self.obsolete = []
            self.running = True
            self.snake = Snake()
            self.cases = []
            super().__init__()
            self.create_window()
            self.mainloop = Thread(target=self.game_mainloop)
    
        def create_window(self):
            """Mise en forme de la fenetre et des tous ses composants"""
            self.grid = QGridLayout()
            self.grid.setContentsMargins(0, 0, 0, 0)
            self.grid.setHorizontalSpacing(1)
            self.grid.setVerticalSpacing(1)
            self.setLayout(self.grid)
    
            self.setWindowTitle("Snake")
            self.resize(1080, 1080)
    
            for i in range(16):
                for a in range(16):
                    case = QWidget()
                    case.setStyleSheet("QWidget {background-color: black;}")
                    self.cases.append(case)
                    self.grid.addWidget(case, i, a)
    
            self.snake.spawn()
            for i in self.snake.body:
                self.cases[i].setStyleSheet("QWidget {background-color: red;}")
    
        def update_grid(self):
            """Cette fonction à pour objectif de mettre à jour la grille
            à chaque fois que elle est appelé"""
    
            for i in range(256):
                if i in self.snake.body:
                    self.cases[i].setStyleSheet("QWidget {background-color: red;}")
                else:
                    self.cases[i].setStyleSheet("QWidget {background-color: black;}")
            print("Update")
    
    
        def keyPressEvent(self, event):
            if event.key() == Qt.Key_Space:
                self.snake.add_case()
                self.update_grid()
            if event.key() == Qt.Key_Z:
                self.snake.direction = "Z"
                self.snake.avance()
                self.update_grid()
            elif event.key() == Qt.Key_S:
                self.snake.direction = "S"
                self.snake.avance()
                self.update_grid()
            elif event.key() == Qt.Key_Q:
                self.snake.direction = "Q"
                self.snake.avance()
                self.update_grid()
            elif event.key() == Qt.Key_D:
                self.snake.direction = "D"
                self.snake.avance()
                self.update_grid()
    
        def game_mainloop(self):
            while self.running:
                self.update_grid()
                time.sleep(1.0)
    
        def closeEvent(self, event):
            event.accept()
            self.running = False
    
    
    
    game = SnakeGame()
    game.show()
    
    
    sys.exit(app.exec_())
    

    La version normal, avec la boucle principale:

    from PyQt5.QtWidgets import QWidget, QGridLayout, QApplication
    from PyQt5.QtCore import Qt
    import sys
    from main import Snake
    import time
    from threading import Thread
    
    app = QApplication(sys.argv)
    
    class SnakeGame(QWidget):
        """Cette classe est la partie graphique du
        jeu snake"""
    
        def __init__(self):
            self.obsolete = []
            self.running = True
            self.snake = Snake()
            self.cases = []
            super().__init__()
            self.create_window()
            self.mainloop = Thread(target=self.game_mainloop)
    
        def create_window(self):
            """Mise en forme de la fenetre et des tous ses composants"""
            self.grid = QGridLayout()
            self.grid.setContentsMargins(0, 0, 0, 0)
            self.grid.setHorizontalSpacing(1)
            self.grid.setVerticalSpacing(1)
            self.setLayout(self.grid)
    
            self.setWindowTitle("Snake")
            self.resize(1080, 1080)
    
            for i in range(16):
                for a in range(16):
                    case = QWidget()
                    case.setStyleSheet("QWidget {background-color: black;}")
                    self.cases.append(case)
                    self.grid.addWidget(case, i, a)
    
            self.snake.spawn()
            for i in self.snake.body:
                self.cases[i].setStyleSheet("QWidget {background-color: red;}")
    
        def update_grid(self):
            """Cette fonction à pour objectif de mettre à jour la grille
            à chaque fois que elle est appelé"""
    
            for i in range(256):
                if i in self.snake.body:
                    self.cases[i].setStyleSheet("QWidget {background-color: red;}")
                else:
                    self.cases[i].setStyleSheet("QWidget {background-color: black;}")
            print("Update")
    
    
        def keyPressEvent(self, event):
            if event.key() == Qt.Key_Space:
                self.snake.add_case()
                self.update_grid()
            if event.key() == Qt.Key_Z:
                self.snake.direction = "Z"
            elif event.key() == Qt.Key_S:
                self.snake.direction = "S"
            elif event.key() == Qt.Key_Q:
                self.snake.direction = "Q"
            elif event.key() == Qt.Key_D:
                self.snake.direction = "D"
    
        def game_mainloop(self):
            while self.running:
                self.snake.avance()
                self.update_grid()
                time.sleep(1.0)
    
        def closeEvent(self, event):
            event.accept()
            self.running = False
    
    
    
    game = SnakeGame()
    game.mainloop.start()
    game.show()
    
    
    sys.exit(app.exec_())
    

    Et enfin, la classe Snake qui elle ne change pas:

    import random
    
    class Snake:
    
        def __init__(self):
            self.direction = "Z"
            self.body = []
    
        def spawn(self):
            """Cette fonction créer le corp du serpent"""
            self.body.clear()
            self.body.append(random.randint(0, 256))
            for i in range(2):
                self.add_case()
    
    
        def add_case(self):
            """Permet de faire grandir le serpent"""
            temp = random.randint(0, 3)
    
            if temp == 0:
                self.body.append(self.body[-1]+1)
            elif temp == 1:
                self.body.append(self.body[-1]-1)
            elif temp == 2:
                self.body.append(self.body[-1]+16)
            elif temp == 3:
                self.body.append(self.body[-1]-16)
    
            self.verification()
    
        def verification(self):
            """Cette fonction vérifie si la valeur ajouté dans le corp
            serpent est conforme ou pas. Si elle ne l'est pas, elle la supprime
            puis refais apelle à self.add_case"""
    
            if self.body[-1] not in range(256) or self.body[-1] in self.body[0:-1]:
                self.body.pop()
                self.add_case()
    
        def avance(self):
            temp = self.body[-1]
            if self.direction == "Z":
                self.haut()
            elif self.direction == "S":
                self.bas()
            elif self.direction == "D":
                self.droite()
            elif self.direction == "Q":
                self.gauche()
            return temp
    
        def haut(self):
            """Cette fonction fais avancer le serpent vers le haut dans la grille"""
    
            temp = self.body[0]
            self.body[0] -= 16
            for i in range(1, len(self.body)):
                self.body[i] , temp = temp, self.body[i]
    
        def bas(self):
            """Cette fonction fais avancer le serpent vers le bas dans la grille"""
    
            temp = self.body[0]
            self.body[0] += 16
            for i in range(1, len(self.body)):
                self.body[i], temp = temp, self.body[i]
    
        def gauche(self):
            """Cette fonction fais avancer le serpent vers la gauche dans la grille"""
    
            temp = self.body[0]
            self.body[0] -= 1
            for i in range(1, len(self.body)):
                self.body[i], temp = temp, self.body[i]
    
        def droite(self):
            """Cette fonction fais avancer le serpent vers la droite dans la grille"""
    
            temp = self.body[0]
            self.body[0] += 1
            for i in range(1, len(self.body)):
                self.body[i], temp = temp, self.body[i]

    Ainsi, vous le verrez, presque rien ne change entre les deux versions, sauf que l'appelle des fonctions n'est simplement pas fais de la même manière. Je vous invites à tester chez vous si jamais pour une meilleur compréhension. Je ne comprend pas du tous à quoi cela est du, c'est pourquoi je m'adresse à vous.

    Merci d'avance pour vos réponses, bonne soirée.


    • Partager sur Facebook
    • Partager sur Twitter

    Problème de boucle d'arrière plan PyQt5

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    • Editeur
    • Markdown