Tutoriel : Création d’un jeu de type Pong avec Python et Pygame

La création de jeux vidéo est une activité parfaite pour initier les élèves et les étudiants à la programmation. Le projet de réaliser un jeu de type Pong, inspiré du célèbre titre commercialisé en 1972, constitue un excellent point d'entrée. Ce tutoriel vous accompagnera pour écrire le programme du jeu Pong. Il est découpé en étapes clés et il sera possible d'avancer à votre rythme sans jamais être bloqué. Pong a été le premier jeu vidéo ayant connu un succès mondial. Le gameplay est très simple et le graphisme limité à son minimum, ce qui en fait l'exercice idéal pour comprendre la boucle de jeu, la gestion des collisions et l'interaction utilisateur.

Introduction à Pygame et l'environnement de développement

Pygame est la bibliothèque libre multiplate-forme que nous utilisons pour faire des jeux. Elle repose sur la bibliothèque SDL, qui gère les appareils d’entrée (clavier, souris, joystick) et de sortie (écran, haut-parleur). Elle permet de programmer la partie multimédia sans se heurter aux difficultés des langages de bas niveau. Pour débuter, Edupython est une distribution clé en main développée par le groupe AmiensPython. Il comprend des librairies utiles pour la programmation, les sciences et les mathématiques au lycée, ainsi que la librairie Pygame. L’interface est intuitive : les programmes sont rédigés dans la zone d'édition, et les tests peuvent être réalisés dans la console.

Avant tout affichage, il faut appeler pygame.init() pour charger l’ensemble des sous-modules. Sans boucle principale, la fenêtre s'ouvre et se referme immédiatement : l’interpréteur Python exécute les instructions ligne après ligne et, une fois la dernière exécutée, le programme se termine. Il faut donc une boucle infinie. La vérification de l'événement pygame.QUIT permet de détecter le clic sur la croix de fermeture et de sortir proprement.

La boucle de jeu : moteur de l'animation

Le cœur de tout jeu Pygame est la boucle de jeu. Contrairement à une requête web classique qui s’exécute une fois et se termine, la boucle de jeu tourne en permanence. Elle interroge les entrées du joueur, calcule la physique et affiche les pixels dans un budget de temps strict, typiquement 16,6 ms pour garantir une expérience fluide à 60 images par seconde.

Sans limitation de vitesse, la boucle principale s’exécute aussi vite que le processeur le permet, rendant les mouvements incohérents d’une machine à l'autre. On instancie l’objet Clock une seule fois avant la boucle, puis on appelle sa méthode tick() à la fin de chaque tour. Une fréquence de rafraîchissement de 30 images par seconde donne un rendu suffisamment fluide. Entre chaque frame, la balle doit se déplacer de $dx$ suivant l’axe $x$ et de $dy$ suivant l’axe $y$. Il existe des opérateurs d’assignation qui permettent de simplifier l’écriture x = x + dx et y = y + dy.

Lire aussi: Oasis Écologique dans Votre Jardin

Représentation graphique et gestion des surfaces

Le contenu graphique dans la fenêtre d'affichage nécessite d'introduire la manière de représenter numériquement les couleurs. Pygame effectue tous ses dessins sur des surfaces rectangulaires. La surface principale, créée avec pygame.display.set_mode(), représente la fenêtre visible. Le terme « blit » désigne un transfert de blocs : copier le contenu d’une Surface vers une autre. Les positions sont toujours exprimées en coordonnées (X, Y), le coin supérieur gauche correspondant à (0, 0).

Il est important de bien comprendre que même si vous n'avez pas d'animation à gérer, il est important d'effacer la surface avant d'afficher une nouvelle image. La ligne surf.fill((0,0,0)) permet d'effacer l'écran avant de réafficher les formes à une position différente. Pour tracer des formes, on utilise les méthodes du module pygame.draw : draw.rect() pour les rectangles, draw.circle() pour les cercles, ou encore draw.line().

Logique de mouvement et détection de collision

Pour simuler le mouvement, on considère qu’à l’instant $t$, la balle est à la position $(x,y)$ dans un repère orthogonal. On peut définir un vecteur position $\vec{p} = \left(\begin{smallmatrix} x \ y \end{smallmatrix}\right)$ ainsi qu’un vecteur déplacement $\vec{d} = \left(\begin{smallmatrix} dx \ dy \end{smallmatrix}\right)$. Mathématiquement, le changement de signe de $dx$ lors d'un rebond revient à multiplier cette valeur par -1.

Le code le plus critique est la gestion de la collision. Il utilise colliderect() de pygame pour détecter la collision entre deux rectangles. Plus précisément, pour qu’il y ait collision entre la balle et la raquette, il faut que le point de la i-ème balle soit tangent ou traverse légèrement le bord de la raquette. La classe pygame.Rect est un outil particulièrement adapté à ces problèmes de collision. left_paddle.top > 0 vérifie si le haut de la raquette est dans les limites, de même pour left_paddle.bottom < HEIGHT.

Structuration du code : Classes et modularité

La programmation objet est sans doute plus adaptée pour un jeu vidéo. Il est préférable de définir la raquette et les balles comme des instances de classes. Trois classes sont généralement définies : Paddle pour les palettes des joueurs, Ball pour gérer la balle qui rebondit, et PongGame pour la logique globale.

Lire aussi: Guide pour lancer sa société de plongée

Si nous manipulons $N$ balles, chaque liste comportera $N$ valeurs de même type. Chaque liste est alors considérée comme une variable unique qui permet de manipuler $N$ valeurs. L'intérêt des boucles for est que la structure du programme pour afficher 1, 3, 10 ou 30 balles est la même. En prévision d'un nombre de balles important, on peut générer les attributs aléatoirement en utilisant la fonction randint() de la librairie random.

Interaction joueur et entrées clavier

L'appui sur une touche est considéré par Pygame comme un nouvel événement. La gestion des événements repose sur le module pygame.event. Chaque événement interrogé est consommé et ne peut être récupéré qu’une seule fois. Il est donc indispensable de traiter la file d’événements à chaque image pour éviter tout retard de réponse.

Les événements KEYDOWN et KEYUP détectent l’appui et le relâchement d’une touche. Pour déplacer la raquette, on utilise les touches de direction. Vous aurez remarqué qu’il faut appuyer plusieurs fois sur les touches pour déplacer la raquette ; maintenir une touche appuyée ne déclenche qu'un seul événement. Pour corriger cela, il faut gérer l'état des touches en continu dans la boucle principale. Le contrôle du jeu est traditionnellement assuré par les touches de direction et Escape pour quitter. On ajoute généralement une touche pour assurer la mise en pause du jeu, souvent attribuée à la touche SPACE.

#

Lire aussi: Design stratégique et exigences techniques d'étiquettes

Articles similaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *