Il s’agit de la troisième partie d’une série de tutoriels en cinq parties sur la création de jeux avec Python 3 et Pygame. Dans la deuxième partie, nous avons couvert la TextObject
classe utilisée pour rendre le texte à l'écran, créer la fenêtre principale et apprendre à dessiner des objets tels que des briques, la balle et la palette.
Dans cette partie, nous allons plonger au cœur de Breakout et apprendre à gérer des événements, à rencontrer le cours principal de Breakout et à voir comment déplacer les différents objets du jeu..
Dans Breakout, il existe trois types d'événements: les événements liés aux touches, aux événements de souris et aux événements de minuterie. La boucle principale de la classe Game prend en charge les événements relatifs aux touches et souris et les transmet aux abonnés (en appelant une fonction de gestionnaire)..
Bien que la classe Game soit très générique et ne possède aucune connaissance spécifique de Breakout, l'abonnement lui-même et la façon de gérer chaque événement sont très spécifiques..
La classe Breakout est l'endroit où sont gérées la plupart des connaissances de domaine relatives au jeu Breakout. Nous rencontrerons le groupe de discussion plusieurs fois au cours de cette série. Voici les lignes qui enregistrent les différents gestionnaires d'événements.
Notez que tout les événements clés pour les flèches gauche et droite iront à la même méthode de gestionnaire de la palette.
# Enregistrez la méthode handle_mouse_event () d'un objet bouton self.mouse_handlers.append (b.handle_mouse_event) # Enregistrez la méthode handle () de la palette pour gérer les événements de clé self.keydown_handlers [pygame.K_LEFT] .append (paddle.handle) self.keydown_handlers [pygame.K_RIGHT] .append (paddle.handle) self.keyup_handlers [pygame.K_LEFT] .append (paddle.handle) self.keyup_handlers [pygame.K_RIGHT] .append (paddle.handle)
La classe Game appellera les gestionnaires enregistrés pour chaque événement clé et transmettra la clé. Notez que ce n'est pas la classe Paddle. Dans Breakout, le seul objet qui s'intéresse à ces événements est la palette. Quand une touche est pressée ou relâchée, son manipuler()
la méthode s'appelle.
Paddle n'a pas besoin de savoir s'il s'agit d'un événement clé en haut ou en bas car il gère l'état actuel via une paire de variables booléennes: Moving_left
et move_right
. Si Moving_left
est True, cela signifie que la flèche gauche est enfoncée et que le prochain événement est la touche haut qui le relâche. Il en va de même pour la flèche vers la droite. La logique est aussi simple que de basculer ces variables en réponse à tout événement.
def handle (self, key): if key == pygame.K_LEFT: self.moving_left = pas self.moving_left sinon: self.moving_right = pas self.moving_right
Breakout a un menu de jeu que vous rencontrerez bientôt. Le bouton du menu gère divers événements de la souris tels que les mouvements et les clics (événements souris vers le bas et souris vers le haut). En réponse à ces événements, le bouton met à jour une variable d'état interne. Voici le code de manipulation de la souris:
def handle_mouse_event (self, type, pos): if type == pygame.MOUSEMOTION: self.handle_mouse_move (pos) elif type == pygame.MOUSEBUTTONDOWN: self.handle_mouse_down (pos) type elif == pygame.MOUSEBUTTONUP: pos) def handle_mouse_move (self, pos): si self.bounds.collidepoint (pos): si self.state! = 'appuyé': self.state = 'survol' autre: self.state = 'normal' def handle_mouse_down (auto , pos): if self.bounds.collidepoint (pos): self.state = 'appuyé' def handle_mouse_up (self, pos): si self.state == 'appuyé': self.on_click (self) self.state = ' flotter'
Notez que le handle_mouse_event ()
La méthode enregistrée pour recevoir des événements de souris vérifie le type de l'événement et le transmet à la méthode spécifique qui gère ce type d'événement..
Les événements de minuterie ne sont pas traités par la boucle principale. Cependant, comme la boucle principale est appelée à chaque image, il est facile de vérifier si un événement chronométré est dû. Vous en verrez un exemple plus tard en discutant des effets spéciaux chronométrés.
Une autre situation concerne le gel du jeu, par exemple lorsque vous affichez un message que le joueur devrait pouvoir lire sans être dérangé. le voir le message()
méthode de la classe Breakout utilise cette approche et appelle le sommeil de temps()
. Voici le code pertinent:
import config en tant que classe c Breakout (jeu): def show_message (self, text, color = colors.WHITE, font_name = "Arial", font_size = 20, centralized = False): message = TextObject (c.screen_width // 2, c .screen_height // 2, lambda: texte, couleur, nom de police, taille de police) self.draw () message.draw (self.surface, centralisé) pygame.display.update () time.sleep (c.message_duration)
La partie gameplay est celle où les règles de Breakout entrent en jeu (vous voyez ce que j’y ai fait?). Le gameplay consiste à déplacer les différents objets en réponse aux événements et à modifier l'état du jeu en fonction de leurs interactions..
Vous avez vu précédemment que la classe Paddle répond aux touches de direction en mettant à jour sa Moving_left
et move_right
des champs. Le mouvement réel se passe dans le mettre à jour()
méthode. Des calculs sont en cours ici si la palette est proche du bord gauche ou droit de l'écran. Nous ne voulons pas que la palette se déplace au-delà des bords de l'écran (y compris un décalage prédéfini).
Donc, si le mouvement l'aurait pris au-delà du bord, le code ajuste le mouvement pour qu'il s'arrête exactement au bord. Puisque la palette ne se déplace que horizontalement, la composante verticale du mouvement est toujours zéro.
import pygame import config en tant que c depuis game_object import, classe GameObject Paddle (GameObject): def __init __ (auto, x, y, w, h, couleur, offset): GameObject .__ init __ (auto, x, y, w, h) self. color = color self.offset = offset self.moving_left = False self.moving_right = False… def update (self): si self.moving_left: dx = - (min (self.offset, self.left)) elif self.moving_right: dx = min (self.offset, c.screen_width - self.right) sinon: retourne self.move (dx, 0)
La balle utilise simplement les fonctionnalités du GameObject
classe de base, qui déplace les objets de jeu en fonction de leur vitesse (avec des composantes horizontales et verticales). La vitesse de la balle est déterminée par de nombreux facteurs de la classe de discussion que vous verrez bientôt. Puisque bouger ne fait qu'ajouter la vitesse à la position actuelle, la direction dans laquelle la balle se déplace est entièrement déterminée par sa vitesse sur les axes horizontal et vertical..
La balle de Breakout apparaît de nulle part au début du jeu à chaque fois que le joueur perd une vie. Il se matérialise juste hors de l'éther et commence à tomber, soit vers le bas, soit sous un léger angle. Quand la balle est créée dans le create_ball ()
méthode, il reçoit une vitesse avec une composante horizontale aléatoire comprise entre -2 et 2 et une composante verticale, qui est déterminée dans le module config.py (actuellement définie sur 3).
def create_ball (self): speed = (random.randint (-2, 2), c.ball_speed) self.ball = Ball (c.screen_width // 2, c.screen_height // 2, c.ball_radius, c.ball_color , vitesse) self.objects.append (self.ball)
Dans cette partie, nous avons traité de la gestion des événements tels que les appuis sur les touches, les mouvements de la souris et les clics de souris. Nous avons également plongé dans certains éléments de jeu de Breakout tels que déplacer la raquette, déplacer la balle et contrôler la vitesse de la balle..
N'oubliez pas également de voir ce que nous avons à vendre et à étudier sur le marché Envato si vous souhaitez étudier davantage de matériel relatif à Python..
Dans la quatrième partie, nous aborderons l’important sujet de la détection des collisions et verrons ce qui se passera lorsque le ballon touchera divers objets du jeu, tels que la raquette, les briques et même les murs, le plafond et le sol..
Ensuite, nous porterons notre attention sur le menu du jeu. Nous allons créer des boutons personnalisés que nous utiliserons comme un menu que nous pourrons afficher et masquer si nécessaire.