Et c'est parti pour le quatrème tuto / cours de SNT, consacré à la découverte de Pygame en Python ! 😃
Pour cette nouvelle étape, nous allons déplacer notre sprite ! 😋
Avant de nous lancer tête bêche dans le code, réfléchissons à ce que nous voulons faire ! 🙃
On veut que notre lapin ninja puisse aller à droite en appuyant sur la flèche droite, s'arrêter si on appuie plus et aller à gauche si on appuie sur la flèche gauche. Cela signifie qu'il va falloir tester les touches du clavier pour voir quelle touche est enfoncée et déplacer notre bonhomme progressivement dans un sens ou dans l'autre. 🧐
Il va aussi falloir lui donner une certaine vitesse (qu'on pourra changer selon le type de jeu qu'on veut faire 🤠).
Et enfin, il faudra l'afficher, en prenant soin de le retourner quand il ira à gauche (sinon, il va faire du Moonwalk comme Michael...). 👻
Bon, dit comme ça, ça a pas l'air trop compliqué ! (Mais, en fait ça va l'être un petit peu quand même...) 🤯
Bon, on va commencer par le plus simple avec le 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" # Taille du sprite du jouer PLAYER_HEIGHTH = 50 PLAYER_WIDTH = 40 # Machine à états NONE = 0 DROITE = 1 GAUCHE = 2 IDLE = 0 WALK = 1 JUMP = 2 DOUBLEJUMP = 3 DEAD = 4 # Timer pour l'animation TIMER = 4 # Vitesse du joueur PLAYER_SPEED = 4 |
Pas grand chose à rajouter ici... Juste un état : NONE quand notre joueur sera immobile et la vitesse de notre joueur : PLAYER_SPEED, qu'on va régler à 4 pour l'instant (mais que vous pourrez changer à la fin pour tester !) 😎
Passons maintenant au Main() (programme principal).
Fichier : Main.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 * from Player import * #Initialisation de pygame pygame.init() clock = pygame.time.Clock() # Ouverture de la fenêtre de jeu en résolution 640 x 360 pixels fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR)) #, pygame.FULLSCREEN|SCALED) #Titre pygame.display.set_caption(TITRE) #Chargement du fond d'écran (background) fond = pygame.image.load(BACKGROUND).convert() #Création du joueur player = Player() # Boucle principale du jeu continuer = True while continuer : # On teste les événements for event in pygame.event.get(): # Si on appuie sur quitter, on ferme le jeu if event.type == QUIT: continuer = False # On teste les appuis sur le touches Gauche / Droite dicKeys = pygame.key.get_pressed() if dicKeys[K_LEFT]: player.input = GAUCHE elif dicKeys[K_RIGHT]: player.input = DROITE elif dicKeys[K_ESCAPE]: continuer = False else: player.input = NONE # On affiche le fond d'écran (background) fenetre.blit(fond,(0,0)) #On met à jour le joueur player.update() # On affiche le sprite player.draw(fenetre) #On rafraichit l'écran pygame.display.update() clock.tick(60) # limite les FPS à 60 pygame.quit() |
Et voilà ! Maintenant, on va expliquer ces modifications pas à pas. 😄
D'abord, j'ai un peu modifié l'ouverture de la fenêtre, pour pouvoir tester le Fullscreen (ou plein écran). Ainsi, si vous enlevez le commentaire # de la ligne suivante, ainsi qu'une parenthèse après HAUTEUR et que vous lancez le jeu, celui-ci prendra tout votre écran ! 😃 Magique, non ? 🤩
# Ouverture de la fenêtre de jeu en résolution 640 x 360 pixels fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR)) #, pygame.FULLSCREEN|SCALED) |
Passons maintenant à la gestion du clavier. Cela fonctionne de la même façon qu'avec toutes les bibliothèques (et forcément plus encore avec la SDL... 😋). On crée une variable dicKeys et on appelle Pygame pour enregistrer dedans la ou les touche(s) du clavier enfoncée(s). On fait ensuite une série de tests (if / elif) pour enregistrer dans player.input si notre joueur doit aller à DROITE, à GAUCHE ou glander ne rien faire : NONE. En fait, c'est plutôt simple ici. 😉
Notez que si on appuie sur la touche ESCAPE / ECHAP, on quitte le jeu en interrompant sa boucle infinie. 🙂
# On teste les appuis sur le touches Gauche / Droite dicKeys = pygame.key.get_pressed() if dicKeys[K_LEFT]: player.input = GAUCHE elif dicKeys[K_RIGHT]: player.input = DROITE elif dicKeys[K_ESCAPE]: continuer = False |
Et voilà, comme d'habitude, passons maintenant à notre dernier fichier ! Là, où les plus gros changements se situent ! ☺️
Ouvrez donc Player.py et mettez à jour 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 * """Classe permettant de créer un personnage""" class Player: 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 = HAUTEUR - PLAYER_HEIGHTH - 40 # Direction du sprite self.direction = DROITE # Animation self.frame = 0 self.timer = TIMER self.state = IDLE self.maxframes = 7 # Gestion des inputs (entrées) clavier self.input = NONE # Mise à jour du sprite def update(self): # On gère le timer (compte à rebours pour faire défiler l'animation) if self.timer < 0: if self.frame < self.maxframes: self.frame += 1 else: self.frame = 0 self.timer = TIMER else: self.timer -= 1 # Gestion des inputs (entrées) clavier if self.input == GAUCHE: if self.x > 5: self.x -= PLAYER_SPEED self.state = WALK self.direction = GAUCHE elif self.input == DROITE: if self.x < LARGEUR - PLAYER_WIDTH: self.x += PLAYER_SPEED self.state = WALK self.direction = DROITE else: self.state = IDLE self.input = NONE |
Premièrement, on va créer notre variable input et la mettre par défaut à NONE, car on veut que notre personnage commence le niveau en étant immobile (il va pas partir sans nous, non plus ! 😮).
Notez que pour gérer la variable input, on doit écrire Player.input quand on est en-dehors de la class (par exemple dans le Main()) et self.input quand on est dedans. C'est logique et ça permet de créer, par exemple deux objets Player (pour le joueur 1 et 2) sans que ceux-ci n'aient les mêmes valeurs. 😁 Mais c'est un petit peu compliqué pour ce tuto (vous pourrez voir ça plus tard dans un autre tuto sur les class). 🧐
# Gestion des inputs (entrées) clavier self.input = NONE |
Ici, on va gérer le déplacement de notre sprite. C'est simple :
- S'il va à gauche :
- On le déplace à gauche en enlevant PLAYER_SPEED de son abscisse x SAUF s'il est à moins de 4 pixels du bord (sinon il va sortir de l'écran et on le reverra peut-être plus jamais... SNIF ! 😅)
- On met son état / state sur WALK / Marche
- On met sa direction à GAUCHE (tout ça sera utile pour savoir comment le dessiner à l'écran)
- S'il va à droite :
- On le déplace à droite en ajoutant PLAYER_SPEED de son abscisse x SAUF s'il est au bord de l'écran à droite (soit la LARGEUR de l'écran moins la LARGEUR du sprite si on ne veut pas qu'il disparaisse... Essayez d'enlever - PLAYER_WIDTH pour voir. Vous allez vite comprendre ! 😂)
- On met son état / state sur WALK / Marche.
- On met sa direction à DROITE.
- S'il ne fait rien :
- On met son état / state sur IDLE / Immobile.
Dans tous les cas, après, on remet input à NONE, sinon, le jeu va croire que la touche reste enfoncée, même si on la relâche !!! 😱
# Gestion des inputs (entrées) clavier if self.input == GAUCHE: if self.x > 5: self.x -= PLAYER_SPEED self.state = WALK self.direction = GAUCHE elif self.input == DROITE: if self.x < LARGEUR - PLAYER_WIDTH: self.x += PLAYER_SPEED self.state = WALK self.direction = DROITE else: self.state = IDLE self.input = NONE |
Et voilà, passons maintenant à l'affichage du sprite ! 😅
Si on commence par le blit de notre personnage à droite, c'est le plus simple, car c'est la même chose que dans le tuto précédent (il s'agit du else).
Là où ça se complique, c'est pour le blit à gauche car il faut retourner notre feuille de sprites en utilisant une variable temporaire spritecopy et en faisant appel à Pygame qui se charge de tout (pygame.transform.flip). Ici, on met le premier flag à True pour un flip vertical, le deuxième à False est pour le flip horizontal. 😉
Maintenant, quand on va à droite, nos frames vont toujours de 0 à 7 comme dans le tuto précédent.
Mais quand on va à gauche, nos frames vont aller de 2 à 9 car on va être obligé de retourner (flip) notre spritesheet et on va donc commencer par deux frames vides (si vous n'y faites pas attention, votre sprite va clignoter comme un sapin de Noël ! 😅).
![]()
On va donc devoir rajouter 2 à la variable frame quand on va à gauche, pour avoir la bonne frame. 😉
# Selon la drection, on oriente le joueur en faisant un flip pour la gauche if self.direction == GAUCHE: spritecopy = pygame.transform.flip(self.sprite, True, False) surface.blit(spritecopy, (self.x, self.y), |
Notez que l'appel à spritecopy n'est pas obligatoire quand on va à droite, mais c'est toujours mieux d'uniformiser le code, par souci de simplicité 😉.
Voilà ! Si vous lancez le jeu en appuyant sur la flèche verte dans le MAIN, vous pourrez maintenant déplacer votre lapin favori de droite à gauche ! Bon jeu ! 😅
A bientôt pour la suite ! 😄

English
Français