Et voilà déjà le second tuto / cours de SNT, consacré à la découverte de Pygame en Python ! 😃
Pour cette nouvelle étape, nous allons afiicher une feuille de sprites ! 😇
Mais, c'est quoi une feuille de sprites ? 🧐
Dans l'industrie du jeu vidéo, c'est l'ensemble des sprites (ou lutins en français 🤡, oui, je sais, c'est moche et personne ne dit ça... 😁) qui constituent les animations d'un personnage en 2D, comme l'animation de l'immobilité (Idle en anglais), la marche (Walk), le saut (Jump), le double saut (Double Jump) ou la mort (death). On peut encore en rajouter d'autres suivant la richesse que l'on veut apporter aux animations de notre jeu (mais attention, trop d'animations peuvent tuer le gameplay - il suffit de regarder certains jeux Infogrames pour s'en convaincre... 🤑).
Normalement, on n'affiche pas toute notre feuille de sprites (ou spritesheet en anglais) à l'écran mais on la découpe pour gérer notre animation 👀. Cela dit, comme nous allons y aller par étapes, nous allons d'abord l'afficher en entier avant de la découper dans les chapitres suivants ! 🤩
Voilà ce que ça devrait nous donner, superposé à notre magnifique background (oui, il faut un Master en anglais pour faire de l'informatique 😹) du chapitre précédent :

Maintenant, on va rajouter notre spritesheet "rabidja.png" dans le dossier "graphics" :

rabidja.png
En plus, de notre fichier Main.py, on va maintenant créer 2 nouveaux fichiers Python vides intitulés Constantes.py et Player.py (ouvrez simplement un nouveau fichier et sauvegardez-le sous ce nom 😉):

Mais pourquoi est-ce qu'on a 3 fichiers maintenant ? 😱 A quoi ça va servir ? 😳
C'est vrai que jusqu'à présent, nos programmes en Python étaient très courts et on n'avait pas besoin d'avoir plusieurs fichiers. Mais vous imaginez bien que si vous programmez un jeu vidéo en open world, vous allez vite vous retrouver avec des centaines de milliers de lignes de code. 😱 Imaginez le bazar, si tout était en vrac dans un seul fichier ! 🤢 Cela deviendrait vite ingérable ! 😰 C'est pour ça, que dans l'industrie, on sépare notre code en plusieurs fichiers, chacun gérant un aspect précis du programme. 😎
Ici, on rajoute deux fichiers :
- Constantes.py qui va contenir toutes les constantes de notre programmes, c'est-à-dire les valeurs prédéfinies (comme par exemple la LARGEUR et la HAUTEUR de notre fenêtre). Comme ça, si un matin on se réveille en ayant envie de changer la valeur d'une constante 🤩, il suffira de la changer UNE SEULE FOIS dans ce fichier plutôt que de galérer à chercher TOUTES LES FOIS où on l'a utilisée dans le code... C'est quand même mieux, non ?... 😇
- Player.py qui va se charger de gérer notre Player / Joueur. C'est là, qu'on va mettre le code pour afficher et gérer les déplacements de Rabidja.
Comme ça, c'est beaucoup plus simple de s'y retrouver. 😉 Et s'il y a un bug, on sait où aller chercher ! D'ailleurs, en parlant de bug : pour les éviter, une bonne pratique est d'écrire juste un petit morceau de code nouveau et ensuite de le tester pour voir s'il fonctionne (quand c'est possible bien sûr 😉). Comme ça, si un nouveau bug surgit, ce sera forcément la faute au dernier bout de code rentré. 🧐 Cela évite de trop chercher ! ☹
Passons maintenant au code source du fichier Constantes.py ! 🤪
Fichier : Constantes.py
# Créé par Jay81, le 16/06/2024 en Python 3.7 """Constantes du jeu""" #Paramètres de la fenêtre LARGEUR = 640 HAUTEUR = 360 #Personnalisation de la fenêtre TITRE = "Rabidja" ICONE = "" #Listes des images du jeu (graphics) BACKGROUND = "graphics/background.png" SPRITE_JOUEUR = "graphics/rabidja.png" # Machine à états DROITE = 1 GAUCHE = 2 JUMP = 3 |
Comme vous pouvez le voir, le code est ici assez transparent. 👻 On crée des variables qui vont être utilisées dans notre code en tant que CONSTANTES. On définit ainsi les dimensions de notre fenêtre (640x360 pixels), le TITRE de notre fenêtre : "Rabidja", et on ne charge pas d'icône pour l'instant. On indique ensuite l'emplacement de nos deux fichiers images (à changer si vous les avez mises ailleurs, parce que vous n'avez rien suivi ! 😡). Enfin, on crée un machine à états (state machine en english 🤡) très simple pour notre héros Rabidja. 😊
Attends ! 🤔 Mais c'est quoi une machine à états, déjà ? 😨
Le principe est simple. On enregistre dans une variable l'état de notre héros selon ce qu'il fait et où il est, et en fonction de ça, on saura comment le gérer et l'animer ! Ici, dans notre exemple, notre héros pourra soit : regarder à DROITE, à GAUCHE et / ou SAUTER. Mais cela deviendra plus clair plus tard. 😋
Rouvrez maintenant le fichier Jeu 02.py qui contient le code du tuto précédent et rajoutez / modifiez le code ci-dessous qui n'apparaît PAS en grisé. C'est parti ! 😎
Fichier : Main.py
# Créé par Jay, le 16/06/2024 en Python 3.7 # Import de pygame import pygame from pygame.locals import * |
Et voilà ! Maintenant, on va expliquer ces modifications pas à pas.
Tout d'abord, on doit importer (import) les fichiers Constantes.py et Player.py pour que le programme sache qu'il doit les inclure à la compilation (il va pas le deviner tout seul... 🙄). Vous remarquerez que ça fonctionne de la même façon que pour notre bibliothèque pygame. 😉
#Import des constantes et classes du jeu from Constantes import * from Player import * |
Ensuite, on fait surtout des modifications, en remplaçant les valeurs qu'on avait mises au chapitre précédent par leurs équivalents dans les CONSTANTES. On remplace ainsi par LARGEUR, HAUTEUR et BACKGROUND.
Notez qu'on rajoute aussi la ligne de code qui permet de définir le TITRE de notre fenêtre à l'aide de la fonction set_caption de Pygame. 😉
# Ouverture de la fenêtre de jeu en résolution 640 x 360 pixels fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR)) #Titre pygame.display.set_caption(TITRE) |
Les deux lignes à changer suivantes vont, en fait, faire appel à notre nouveau fichier Player.py que nous allons implémenter juste après. Vous comprendrez mieux, une fois qu'on l'aura vu. 🤪
D'abord, on va dire au programme de créer un joueur (player) en appelant la méthode / fonction Player() que nous verrons ci-dessous. 😉
Notez que l'on note :
- player = une variable
- Player() = une méthode ou fonction, c'est-à-dire un bout de code qui va s'exécuter.
Il ne faut surtout pas tout mélanger ! 😨
#Création du joueur
player = Player()
|
Ensuite, dans notre boucle infinie, on rajoute l'affichage (blit) de notre feuille de sprite (spritesheet), un peu comme le fond d'écran précédemment. Comme arguments (les trucs entre parenthèses 😜), on lui envoie player.sprite qui contiendra notre spritesheet (image) et les coordonnées où blitter (afficher) : player.x et player.y. Mais on verra ça dans le fichier Player.py ! 🤩
Attention, à ne PAS INVERSER l'affichage du background et de la feuille de sprite, sinon, la spritesheet sera recouverte par le fond et on ne la verra donc PAS ! 😱
# On affiche le sprite
fenetre.blit(player.sprite, (player.x, player.y))
|
Et voilà, passons maintenant à notre dernier fichier ! ☺️
Ouvrez donc Player.py et recopiez le texte ci-dessous :
Fichier : Player.py
# Créé par Jay81, le 16/06/2024 en Python 3.7 # Import de pygame import pygame from pygame.locals import * #Import des constantes et classes du jeu from Constantes import * class Player: """Classe permettant de créer un personnage""" def __init__(self): # Chargement du fichier du sprite self.sprite = pygame.image.load(SPRITE_JOUEUR).convert_alpha() # Coordonnées du sprite self.x = 0 self.y = 0 # Direction du sprite self.direction = DROITE |
Pour l'instant, c'est assez court car notre joueur ne fait pas grand chose... 😬
Rappelez-vous, on affiche juste sa feuille de sprite (spritesheet) ! 😉
Bon, le début, vous connaissez déjà. 😉 Comme pour le programme principal (qu'on a appelé Jeu 02 mais qu'on appelle plus généralement le main, soit le programme principal), on doit importer Pygame et nos Constantes. C'est très important de le faire dans CHAQUE FICHIER sinon, on ne pourra pas les utiliser dans cette partie du programme. 😥
# Import de pygame import pygame from pygame.locals import * #Import des constantes et classes du jeu from Constantes import * |
C'est là où ça se corse un peu, mais on va essayer de faire simple. SI vous voulez rentrer plus dans les détails, vous irez voir d'autres tutos plus développés comme celui en C++ de notre ami Gondulzak ! 😉
Alors, on va créer une class nommée Player:.
Mais c'est quoi une class ?
D'après la doc officielle de Python :
"Les classes sont un moyen de réunir des données et des fonctionnalités. Créer une nouvelle classe crée un nouveau type d'objet et ainsi de nouvelles instances de ce type peuvent être construites. Chaque instance peut avoir ses propres attributs, ce qui définit son état. Une instance peut aussi avoir des méthodes (définies par la classe de l'instance) pour modifier son état." Lire la suite.
C'est une composante essentielle de la programmation orientée objet. Pour essayer de simplifier au maximum, on va créer un objet / une class Player: qui va contenir tout ce qui est nécessaire à la création et à la gestion de notre joueur. Depuis notre main(), il nous suffira de l'appeler et tout le code nécessaire au joueur ainsi que ses variables seront contenus dedans. C'est très pratique, car on peut ainsi facilement réutiliser une class d'un projet à l'autre sans devoir tout réécrire. 😉
class Player: """Classe permettant de créer un personnage""" |
Pour l'instant, notre class ne va contenir qu'une seule méthode : def qui est la fonction de base qui permet de créer l'objet (c'est pour ça qu'on a self, car il se crée lui-même 😉).
Dedans, on va d'abord charger la spritesheet (feuille de sprites) de notre héros, qu'on va enregistrer dans la variable sprite. Notez que convert_alpha permet de gérer la transparence de notre image pour ne pas avoir un fond noir derrière Rabidja 😜.
On définit ensuite les coordonnées x et y de notre joueur. Ici, on va l'afficher à (0,0) soit le haut gauche de l'écran (Ah, oui, parce qu'avec la SDL le point de départ du repère orthonormé est en haut à gauche, ça peut être un peu perturbant au départ, quand on est habitué aux maths... 😵)
Et enfin, on donne une direction de départ à notre sprite pour qu'il s'affiche vers la DROITE (pas encore vraiment utile ici... 🙃)
def __init__(self): # Chargement du fichier du sprite self.sprite = pygame.image.load(SPRITE_JOUEUR).convert_alpha() # Coordonnées du sprite self.x = 0 self.y = 0 # Direction du sprite self.direction = DROITE |
Voilà ! Maintenant, si vous cliquez sur la flèche verte en haut d'Edupython en ayant le fichier Main.py d'ouvert (sinon ça ne marchera PAS !!!), ça va lancer le programme et ce bon vieux Rabidja va apparaître avec sa feuille de sprite ! 😇
Bon c'est mieux, mais on n'y est pas encore ! 😅 Au chapitre suivant, on anime ce lapin furieux ! 😁
A bientôt pour la suite ! 😄

English
Français