Plus loin avec le module sprite, exemples appliqués
Introduction
Le propos du présent chapitre est d’approfondir l’utilisation des sprites en Pygame, en expérimentant entre autres les facilités offertes en ce qui concerne la gestion des collisions. Nous allons donc créer plusieurs jeux vidéo utilisant toutes les notions étudiées auparavant, à commencer bien sûr par les sprites.
Le présent chapitre s’articule autour de plusieurs exemples de jeux vidéo. Un jeu du serpent (snake) tout d’abord, qui est pour le moins mythique. Le principe du jeu du serpent est que sa tête ne doit jamais rencontrer son corps (auquel cas, il perd). Mais à chaque fois qu’il mange de la nourriture, il gagne un point et grandit, ce qui rend difficile (et amusant) le déplacement au bout d’un certain temps. La nourriture apparaît de manière aléatoire et disparaît. On déplace le serpent à l’aide du pavé directionnel.
Nous poursuivrons par un petit jeu de labyrinthe dans lequel sont disposés des objets. Le but pour le personnage est de ramasser tous les objets en se déplaçant au sein du labyrinthe. On chronomètre la performance. Là encore, on déplace le personnage à l’aide du pavé directionnel.
Nous construirons ensuite un jeu de casse-briques. Comme le jeu du serpent, c’est un classique du jeu vidéo. Le joueur déplace latéralement une raquette qui lui permet de faire rebondir une balle. La balle peut casser un ensemble de briques placées en haut de l’écran. Le but est évidemment de casser toutes les briques.
Enfin, nous reprendrons le jeu Fusée et planètes du chapitre Concepts du jeu vidéo et premiers pas à propos de Pygame. Mais cette fois, nous le coderons en utilisant des sprites.
Le jeu du serpent (snake)
1. Le contexte
Comme précisé juste avant, ce jeu est effectivement mythique. Il a été inventé en 1976, a été implémenté sur nombre de systèmes et tire son originalité dans le fait que l’entrave au déplacement du serpent est, au bout d’un certain temps... le serpent lui-même. En effet, le serpent grandit à chaque fois qu’il absorbe de la nourriture. Quand le serpent mange de la nourriture, on gagne un point. Enfin, la nourriture apparaît à des endroits choisis aléatoirement et qui restent affichés quelques secondes. Ensuite, d’autres éléments de nourriture apparaissent ailleurs et disparaissent, etc.
2. Les images utilisées
On commence par définir les images qui vont servir dans ce jeu.
-
Une image pour représenter la tête du serpent. Peu importe son orientation. On gère ceci programmatiquement, avec des rotations.
-
Une image représentant un élément du corps du serpent.
-
Une image représentant la nourriture violette ingurgitée par le serpent.
Ci-après les trois images au format PNG. On doit absolument avoir les mêmes dimensions pour chacune des images de manière à être sûr que l’approche par sprites ne sera pas perturbée. Chacune des images est ainsi de forme carrée et de dimension 32 pixels sur 32 pixels.
-
Tête du serpent :
-
Corps du serpent :
-
Un élément de nourriture :
3. Les effets sonores utilisés
On envisage deux effets sonores : un effet sonore joué dès que de la nourriture apparaît et quand elle est mangée par le serpent, un autre effet sonore quand le jeu est perdu. Les deux fichiers sont d’extension .wav.
4. Le programme global
Voici d’ores et déjà...
Le jeu du labyrinthe
1. Le contexte
On définit un petit jeu du labyrinthe dont le but est de ramasser les dix objets disposés aléatoirement dans les couloirs du labyrinthe en un minimum de temps. On affichera donc un chronomètre pour que le joueur ait devant les yeux le temps qui défile.
On pressent d’emblée la gestion des collisions qu’il y aura à faire :
-
On veut vérifier que les objets sont bien dans des couloirs et non sur les murs du labyrinthe. Il faut que les objets soient accessibles par le personnage.
-
Quand le personnage ramasse un objet, il s’agit d’une collision qu’il faut gérer un petit peu comme quand le serpent (jeu précédent) mange de la nourriture.
On aurait pu placer le personnage à une entrée et avec la mission supplémentaire de sortir par une sortie donnée après avoir ramassé tous les objets, mais l’essentiel du développement et de la manipulation des sprites n’est pas là. Ce choix permet par ailleurs de simplifier l’exemple et de le rendre plus lisible.
2. Conception du labyrinthe
On commence par réfléchir à comment afficher le labyrinthe. Il faut définir son tracé et bien vérifier que chaque point du labyrinthe est relié à n’importe quel autre point du labyrinthe, de manière à être sûr que le personnage sera en mesure de récupérer tous les objets. Si l’on envisage le labyrinthe comme un réseau, on souhaite donc définir un réseau connexe.
L’approche la plus judicieuse est de définir le labyrinthe dans un fichier externe et de définir un code pour signifier qu’il y a à tel endroit un mur et à tel autre endroit un couloir.
On a ci-après le contenu du fichier Labyrinthe.txt dans lequel...
Le jeu de casse-briques
1. Le contexte
Le jeu d’arcade de casse-briques (breakout en anglais) remonte au tout début du jeu vidéo. Il aurait été implémenté dès 1975, et depuis, des dizaines de jeux de ce type existent, s’exécutant sur les plateformes les plus variées. C’est par ailleurs un jeu qui peut se prêter à l’ajout de plusieurs niveaux (levels).
Le but est donc de marquer des points en cassant des briques avec une balle que l’on fait rebondir sur une raquette placée en bas de la fenêtre de jeu. Attention, si la balle atteint le bas de la fenêtre de jeu, qu’elle a été ratée par la raquette, alors la partie est perdue.
2. Les images utilisées
Une fois encore, les images correspondent à la dimension exacte de la taille des futurs sprites.
On a trois images de formes géométriques très simples qui peuvent être créées avec un logiciel de dessin comme Gimp.
-
Une balle de couleur verte :
-
Un élément « brique » de couleur bleue :
-
Une raquette de couleur orange :
3. Le programme global
On a ici deux fichiers :
-
CLASSES.py inclut les classes du jeu ainsi que les constantes.
-
CASSE-BRIQUES.py comprend l’algorithme du jeu et la boucle de jeu elle-même.
On utilise dans ce programme l’opérateur +=. Ce dernier consiste à ajouter une valeur numérique à la valeur de la variable de gauche et à lui affecter la somme obtenue. Exemple :
>>> x = 4
>>> x += 3
>>> print(x)
7
CLASSES.py
import pygame
LARGEUR, HAUTEUR = 640, 480
BALLE_LARGEUR, BALLE_HAUTEUR = 16, 16
BRIQUE_LARGEUR, BRIQUE_HAUTEUR = 64, 16
RAQUETTE_LARGEUR, RAQUETTE_HAUTEUR = 64, 16
RAQUETTE_VITESSE = 20
BALLE_VITESSE...
Le jeu de défilement : Fusée et planètes (version 2)
1. Le contexte
On reprend ici le jeu du chapitre Concepts du jeu vidéo et premiers pas à propos de Pygame, codé sans utiliser le module sprite, ce qui induit des calculs géométriques assez fastidieux pour contrôler les éventuelles collisions entre fusée et planètes. En effet, le but du jeu est d’éviter avec la fusée qui bouge latéralement les planètes qui défilent de haut en bas.
2. Le programme global
On a trois fichiers Python dans le jeu.
-
Le fichier Main.py d’origine.
-
Le fichier CLASSES.py qui inclut les deux classes FUSEE et PLANETE.
-
Le fichier CONSTANTES.py qui regroupe les différentes constantes du jeu.
CONSTANTES.py
from random import *
HAUTEUR_FENETRE = 600
LARGEUR_FENETRE = 600
COULEUR_FOND = (255, 255, 250)
ARRET_JEU = False
LARGEUR_FUSEE = 88
HAUTEUR_FUSEE = 175
MOUVEMENT_XX_FUSEE = 0
XX_PLANETE = randint(30, 130)
YY_PLANETE = 20
LARGEUR_PLANETE = 111
HAUTEUR_PLANETE = 80
XX_ENTRE_PLANETES = 350
YY_ENTRE_PLANETE = 125
VITESSE_PLANETES = 3
CLASSES.py
import pygame, random, sys
from CONSTANTES import *
from datetime import timedelta, datetime, date, time
LISTE_PLANETES = pygame.sprite.Group()
LISTE_GLOBALE_SPRITES = pygame.sprite.Group()
class PLANETE(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load("img/PLANETE.png").convert_alpha()
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def update(self):
self.rect.y = self.rect.y + VITESSE_PLANETES
if...