Construire des jeux avec Python 3 et Pygame Partie 1

Vue d'ensemble

Beaucoup de développeurs se lancent dans le développement de logiciels car ils veulent créer des jeux. Tout le monde ne peut pas être un développeur de jeux professionnel, mais tout le monde peut créer ses propres jeux pour s'amuser et peut-être même en tirer profit. Dans cette série en cinq parties, je vais vous montrer comment créer des jeux en un seul joueur 2D avec Python 3 et l'excellent framework Pygame.. 

Nous allons construire une version du jeu classique Breakout. En fin de compte, vous aurez une idée claire de ce qu’il faut pour créer votre propre jeu, vous serez familiarisé avec les fonctionnalités de Pygame et vous aurez un exemple de jeu.. 

Voici les fonctionnalités et fonctionnalités que nous allons implémenter:

  • GameObject et TextObject génériques simples
  • objet de jeu générique simple
  • bouton générique simple
  • fichier de configuration
  • gestion des événements clavier et souris
  • briques, pagaie et balle
  • gestion du mouvement de la pagaie
  • gérer les collisions de la balle avec tout
  • image de fond
  • effets sonores
  • système extensible d'effets spéciaux

Ce que vous ne devrait pas attendre est un jeu visuellement agréable. Je suis un programmeur et non un artiste. Je m'inquiète davantage de l'esthétique du code. Le résultat de ma conception visuelle peut être assez choquant. Sur le plan positif, si vous souhaitez améliorer l’apparence de cette version de Breakout, vous devez des tonnes de la marge d'amélioration. Après cet avertissement, voici une capture d'écran:

Le code source complet est disponible ici.

Introduction rapide à la programmation de jeux

Les jeux consistent à déplacer des pixels sur l'écran et à faire du bruit. Pratiquement tous les jeux vidéo / informatiques contiennent la plupart des éléments suivants. Les jeux client-serveur et les jeux multijoueurs, qui impliquent également beaucoup de programmation réseau, ne relèvent pas de cet article..

Boucle principale

La boucle principale d'un jeu s'exécute et rafraîchit l'écran à intervalles fixes. Ceci est votre fréquence d'images et elle détermine la régularité des choses. En règle générale, les jeux actualisent l'écran 30 à 60 fois par seconde. Si vous allez plus lentement, les objets à l'écran sembleront saccadés. 

Dans la boucle principale, il y a trois activités principales: gérer les événements, mettre à jour l'état du jeu et dessiner l'état actuel de l'écran..

Gestion des événements

Les événements dans un jeu comprennent tout ce qui se passe en dehors du contrôle du code du jeu, mais qui est pertinent pour le fonctionnement du jeu. Par exemple, si le joueur appuie sur la flèche gauche dans la discussion, le jeu doit déplacer la palette vers la gauche. Les événements typiques sont les pressions sur les touches (et les relâchements), les mouvements de la souris, les clics de souris (en particulier dans les menus) et les événements de la minuterie (par exemple, un effet spécial expire au bout de 10 secondes)..

État de mise à jour

Le cœur de chaque jeu est son état: tout ce qu’il garde et dessine à l’écran. Dans Breakout, l'état inclut l'emplacement de toutes les briques, la position et la vitesse de la balle, ainsi que la position de la raquette, ainsi que les vies et le score.. 

Il y a aussi l'état auxiliaire qui aide à gérer le jeu: 

  • Sommes-nous en train de montrer un menu maintenant? 
  • Est-ce que le jeu est terminé? 
  • Le joueur a-t-il gagné?

Dessin

Le jeu doit afficher son état à l'écran. Cela comprend le dessin de formes géométriques, d’images et de texte.

Physique du jeu

La plupart des jeux simulent un environnement physique. En évasion, la balle rebondit sur les objets et a une très système physique brut de corps rigide en place (si vous pouvez l'appeler ainsi). 

Les jeux plus avancés peuvent avoir des systèmes de physique plus sophistiqués et réalistes (en particulier les jeux 3D). Notez que certains jeux comme les jeux de cartes n'ont pas beaucoup de physique, et c'est très bien. 

IA (intelligence artificielle)

Il existe de nombreux jeux où vous jouez contre un ou des adversaires artificiels, ou des ennemis tentent de vous tuer ou pire. Ces produits de l'imagination du jeu se comportent souvent de manière apparemment intelligente dans le monde du jeu.. 

Par exemple, les ennemis vous poursuivront et connaîtront votre position. Breakout ne présente pas une IA. Vous jouez contre les briques froides et dures. Cependant, l'IA dans les jeux est souvent très simple et ne fait que suivre des règles simples (ou complexes) pour obtenir des résultats pseudo-intelligents..

Lecture audio

La lecture audio est un autre aspect important des jeux. Il existe généralement deux types d’audio: la musique de fond et les effets sonores. Dans Breakout, je me concentre sur les effets sonores qui jouent brièvement lorsque divers événements se produisent. 

La musique de fond est juste une musique qui joue constamment en arrière-plan. Certains jeux n'utilisent pas de musique de fond et d'autres changent de niveau..

Vies, scores et niveaux

La plupart des jeux vous donnent un certain nombre de vies, et lorsque vous êtes à court de vies, le jeu est terminé. Vous avez également souvent un score qui vous donne une idée de votre performance et une motivation pour améliorer la prochaine fois que vous jouez ou tout simplement vous vanter auprès de vos amis au sujet de vos compétences folles de Breakout. Beaucoup de jeux ont des niveaux complètement différents ou qui augmentent le niveau de difficulté.

Rencontrez Pygame

Avant de plonger et de commencer à mettre en œuvre, apprenons un peu plus sur Pygame, qui fera beaucoup pour nous..

C'est quoi Pygame?

Pygame est un framework Python pour la programmation de jeux. Il est construit sur SDL et contient tous les avantages:

  • mature
  • grande communauté
  • Open source
  • multiplate-forme
  • bons docs
  • beaucoup de jeux d'échantillons
  • Facile à apprendre

Installer Pygame

Type pip installer pygame afin de l'installer. Si vous avez besoin de quelque chose d'autre, suivez les instructions de la section Mise en route du wiki. Si vous utilisez macOS Sierra comme moi, vous risquez de rencontrer des problèmes. J'ai pu installer Pygame sans aucun problème et le code semblait fonctionner correctement, mais la fenêtre de jeu ne s'est jamais affichée.. 

C'est une sorte de déception quand vous lancez une partie. J'ai finalement dû utiliser Windows dans une machine virtuelle VirtualBox. Si tout va bien, au moment où vous lirez cet article, le problème aura été résolu.

Architecture du jeu

Les jeux doivent gérer beaucoup d'informations et effectuer des opérations similaires sur de nombreux objets. Breakout est un mini-jeu, mais essayer de tout gérer dans un seul fichier serait accablant. Au lieu de cela, j'ai choisi de créer une structure et une architecture de fichier qui conviendraient à des jeux beaucoup plus volumineux..

Répertoire et structure de fichier

├── Pipfile ├── Pipfile.lock ├── README.md ball.py breakout.py brick.py bouton.py couleurs.py config .py ├── game.py game_object.py images └── background.jpg paddle.py sound_effects brick_hit.wav ├── effect_done.wav ├── level_complete.wav paddle_hit.wav └── text_object.py 

Pipfile et Pipfile.lock sont le moyen moderne de gérer les dépendances en Python. Le répertoire images contient les images utilisées par le jeu (uniquement l'image d'arrière-plan de cette incarnation), et le répertoire sound_effects contient de courts clips audio utilisés comme effets sonores (vous l'avez deviné). 

Les fichiers ball.py, paddle.py et brick.py contiennent du code spécifique à chacun de ces objets Breakout. Je les couvrirai en profondeur plus tard dans la série. Le fichier text_object.py contient le code permettant d'afficher du texte à l'écran et le fichier background.py contient la logique de jeu spécifique à Breakout.. 

Cependant, plusieurs modules forment un squelette lâche et polyvalent. Les classes définies ici peuvent être réutilisées pour d'autres jeux basés sur Pygame.

La classe GameObject

GameObject représente un objet visuel qui sait se rendre lui-même, conserver ses limites et se déplacer. Pygame a en fait une classe Sprite qui a un rôle similaire, mais dans cette série, je veux montrer comment les choses fonctionnent à un niveau bas et ne pas compter sur trop de magie préemballée. Voici la classe GameObject:

from pygame.rect import Rect classe GameObject: def __init __ (auto, x, y, w, h, vitesse = (0,0)): self.bounds = Rect (x, y, w, h) self.speed = vitesse @property def left (self): retourne self.bounds.left @property def right (auto): retour self.bounds.right @property def top (auto): retour self.bounds.top @property def bottom (auto): return self.bounds.bottom @property def width (self): retourne self.bounds.width @property def height (self): retourne self.bounds.height @property def centre (self): retourne self.bounds.center @property def centerx (self): retour self.bounds.centerx @property def centery (self): retour self.bounds.centery def draw (self, surface): passe def move (self, dx, dy): self.bounds = self .bounds.move (dx, dy) def update (self): si self.speed == [0, 0]: retourne self.move (* self.speed) 

GameObject est conçu pour servir de classe de base pour d'autres objets. Il expose directement un grand nombre des propriétés de son rectangle. mettre à jour() méthode il déplace l'objet en fonction de sa vitesse actuelle. Il ne fait rien dans son dessiner() méthode, qui devrait être remplacée par des sous-classes.

La classe de jeu

La classe de jeu est le cœur du jeu. Il exécute la boucle principale. Il a beaucoup de fonctionnalités utiles. Prenons ça méthode par méthode.

le __init __ () Cette méthode initialise Pygame lui-même, le système de polices et le mélangeur audio. La raison pour laquelle vous devez passer trois appels différents est que tous les jeux Pygame n'utilisent pas tous les composants. Vous contrôlez ainsi les sous-systèmes que vous utilisez et initialisez uniquement ceux avec leurs paramètres spécifiques. Il crée l’image d’arrière-plan, la surface principale (où tout est dessiné) et l’horloge de jeu avec le taux de trame correct.. 

Le membre self.objects conservera tous les objets de jeu devant être rendus et mis à jour. Les différents gestionnaires gèrent les listes de la fonction de gestionnaire à appeler lorsque certains événements se produisent..

import pygame import sys des collections import defaultdict classe Jeu: def __init __ (auto, légende, largeur, hauteur, nom_fichier_image, frame_rate): self.background_image = \ pygame.image.load (nom_fichier_image) self.frame_rate = frame_rate self.game_over = false self.objects = [] pygame.mixer.pre_init (44100, 16, 2, 4096) pygame.init () pygame.font.init () self.surface = pygame.display.set_mode ((largeur, hauteur)) pygame. display.set_caption (caption) self.clock = pygame.time.Clock () self.keydown_handlers = defaultdict (liste) self.keyup_handlers = defaultdict (liste) self.mouse_handlers = [] 

le mettre à jour() et dessiner() les méthodes sont très simples. Ils parcourent simplement tous les objets de jeu gérés et appellent les méthodes correspondantes. Si deux objets du jeu se chevauchent, l'ordre dans la liste d'objets détermine quel objet sera rendu en premier, et l'autre le recouvrira partiellement ou complètement.. 

 def update (self): pour o dans self.objects: o.update () def draw (self): pour o dans self.objects: o.draw (self.surface) 

le handle_events () method écoute les événements générés par Pygame, tels que les événements de touche et de souris. Pour chaque événement, il appelle toutes les fonctions de gestionnaire enregistrées pour gérer ce type d'événement..

 def handle_events (self): for event in pygame.event.get (): if event.type == pygame.QUIT: pygame.quit () sys.exit () elif event.type == pygame.KEYDOWN: pour le gestionnaire self.keydown_handlers [event.key]: gestionnaire (event.key) elif event.type == pygame.KEYUP: pour le gestionnaire dans self.keydown_handlers [event.key]: handler (event.key) elif event.type in (pygame) .MOUSEBUTTONDOWN, pygame.MOUSEBUTTONUP, pygame.MOUSEMOTION): pour le gestionnaire dans self.mouse_handlers: gestionnaire (event.type, event.pos) 

Finalement, le courir() La méthode exécute la boucle principale. Il court jusqu'au jeu terminé le membre devient vrai. A chaque itération, il restitue l’image d’arrière-plan et appelle pour que le handle_events (), mettre à jour(), et dessiner() les méthodes. 

Ensuite, il met à jour l'affichage, qui met à jour l'affichage physique avec tout le contenu rendu lors de cette itération. Dernier point, mais non le moindre, il appelle le clock.tick () méthode pour contrôler quand la prochaine itération sera appelée.

 def run (self): bien que self.game_over: self.surface.blit (self.background_image, (0, 0)) self.handle_events () self.update () self.draw () pygame.display.update () self.clock.tick (self.frame_rate)

Conclusion

Dans cette partie, vous avez appris les bases de la programmation de jeux et tous les composants nécessaires à la création de jeux. Ensuite, nous avons examiné Pygame lui-même et son installation. Enfin, nous avons approfondi l’architecture du jeu et examiné la structure des répertoires, la GameObject classe et la classe Game. 

Dans la deuxième partie, nous examinerons le TextObject classe utilisée pour rendre le texte à l'écran. Nous allons créer la fenêtre principale, y compris une image d'arrière-plan, puis apprendre à dessiner des objets comme la balle et la palette..

De plus, s'il vous plaît, voyez ce que nous avons à vendre et à étudier sur le marché Envato, et n'hésitez pas à poser des questions et à fournir vos précieux commentaires en utilisant le flux ci-dessous.