Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site
Il s'agit du premier des chapitres sur la bibliothèque Pygame
Pygame est une bibliothèque libre multiplate-forme qui facilite le développement de jeux vidéo temps réel avec le langage
de programmation Python.
Construite sur la bibliothèque SDL (Simple DirectMedia Layer), elle permet de programmer la partie multimédia
(graphismes, son et entrées au clavier, à la souris ou avec joystick)
sans se heurter aux difficultés des langages de bas niveaux comme le C.
Pygame est donc une couche logicielle entre le développeur et la bibliothèque SDL.
Pour installer Pygame il suffit d'utiliser l'utilitaire pip.
La commande à partir de l'invite de commande windows :
pip install pygame
Pygame installée, tapez "import pygame" dans la console Python.
>>> import pygame pygame 2.5.2 (SDL 2.28.3, Python 3.9.1) Hello from the pygame community. https://www.pygame.org/contribute.html >>>
J'ai donc installé la version 2.5 de pygame qui inclut la version 2.28 de SDL).
Je vous invite à écrire le script ci-dessous puis de l'exécuter.
Il s'agit d'un jeu basique. Avec les touches de direction gauche et droite vous déplacer le carré vert pour éviter une collision avec le carré rouge qui balaie la fenêtre de jeu de gauche à droite. Dès qu'il y a collision entre les deux carrés, le jeu s'arrête. L'objectif est donc de tenir le plus longtemps.
Les carrés sont les "sprites" de ce jeu.
Créez un dossier à la racine de c: et nommez le "pygame_prog".
Enregistrez le programme sous le nom "premier_jeu.py".
Ne cherchez pas à comprendre ce code pour l'instant. C'est prématuré !
Je vous demande de vous imprégnier de la nouvelle syntaxe découlant de l'emploi de la bibliothèque pygame.
Notez que les couleurs sont exprimées selon le code RGB (Red Greeen Blue) sous forme d'un tuple de trois entiers compris chacuns entre 0 et 255.
Exemples de notation des couleurs :
rouge = (255, 0, 0) vert = (0,255,0) bleu = (0, 0, 255)
Ces différentes couleurs sont utilisées pour remplir la fenêtre de jeu et les formes dessinées (des carrés ici).
Vous verrez dans un chapitre ultérieur que l'on peut utiliser aussi les noms (anglais bien sûr) des couleurs.
Exécutez le programme à partir de l'IDLE OU à partir de l'invite de commandes (après avoir sélectionné le bon répertoire).
Si vous trouvez que c'est trop lent/trop rapide il suffit de modifier l'instruction "vitesse =20" qui indique le nombre d'itérations de la boucle de jeu par seconde.
Attention je triche !
En effet le rendu ci-dessus ne correspond pas à un programme Pygame-Python mais à une page HTML (avec aussi du SVG & JS).
En effet un programme Python ne peut pas tourner dans un navigateur (pas encore ...)
Donc pour développer des jeux en ligne (exécutés par un navigateur) il faut mieux recourir à JavaScript.
La fenêtre de jeu est munie d’un système de coordonnées orthonormé.
L’origine du repère (le point 0, 0), est le coin supérieur gauche de la fenêtre.
L’axe des Y est l’axe vertical orienté vers le bas.
L’axe des X est l’axe horizontal orienté vers la droite.
Tous les programmes qui suivent seront stockés dans le dossier "pygame_prog" (à la racine de c:).
Il faut bien sur importer la bibliothèque (tous les modules).
Pygame.init() : initialise tous les modules de pygame.
Avec la troisième instruction on définit une fenêtre de jeu de 400 par 400.
Notez que la fonction display.set_mode() est argumentée avec un tuple (largeur, hauteur).
Exécutez ce programme à partir de l'invite de commandes (après avoir sélectionné le bon répertoire).
C:\Users\boulanger>cd c:\pygame_prog c:\pygame_prog>py pygame_test0.py
La fenêtre de jeu s'affiche puis disparait aussitôt.
Un programme de jeu doit comporter obligatoirement une boucle de jeu !
Le programme comporte une boucle de jeu sous forme d'une boucle infinie.
Exécutez ce programme à partir de l'invite de commandes.
Une fenêtre de jeu (avec un fond noir) s'affiche.
Problème : on n'arrive pas à la fermer même en cliquant sur le bouton de fermeture ...
La fenêtre a pour titre "pygame window" ; c'est la légende par défaut de la barre de titre de la fenêtre.
Vous pouvez aussi exécuter un programme Python à partir de l'explorateur de fichiers. Il suffit de double-cliquer sur le fichier d'extension .py.
J'introduis maintenant la gestion des évènements avec Pygame.
Avec la fonction display.set_caption() je personnalise la légende de la fenêtre de jeu.
La fonction pygame.event.get() permet d’intercepter tous les événements entrants notamment depuis le clavier, la souris, etc.
Ici on quitte la boucle de jeu si on clique sur le bouton X de la fenêtre de jeu.
En effet si le test (if event.type ==pygame.QUIT )
retourne VRAI alors la valeur de la variable boucle_jeu passe à False donc on sort de la boucle infinie.
Attention, les événements sont des constantes qui doivent être écrites en majuscules.
La fenêtre s'affiche avec le texte "Ma fenêtre" dans la barre de titre.
Ce programme sera le squelette de tous les programmes futurs.
Cliquez sur X ; la fenêtre se ferme.
En effet ce script comprend une boucle de jeu et la possibilité pour l'utilisateur de la quitter.
Avant d'insérer des images, redéfinissez éventuellement leurs dimensions afin qu'elles ne fassent que quelques dizaines de pixels
tant en hauteur qu'en largeur (utilisez à cette fin le logiciel Paint).
Je rappelle que pour lancer ce logiciel il suffit de tapez "paint" dans la zone "rechercher" de la barre d'état.
Laissez ouvert la fenêtre de jeu une dizaine de secondes. Le compteur affiche plusieurs milliers ... Donc le nombre d'itérations de la boucle de jeu par seconde est énorme ; alors que 24 images à la seconde suffisent pour donner de la fluidité. 24 est d'ailleurs le nombre d'images à la seconde d'un film.
Mais il est possible de gérer la FPS (Fréquence Par Seconde) : nombre d'itérations par seconde de la boucle de jeu.
Je vais désormais gérer le nombre d'itérations par seconde de la boucle de jeu.
Je crée donc un objet de type pygame.time.clock que je nomme frequence
La méthode tick(frame) d'un objet pygame.time.Clock se place dans la boucle et prend en argument le nombre d'itérations par seconde de la boucle de jeu.
Le rendu :
Laissez la fenêtre de jeu ouverte une dizaine de secondes ; le compteur affiche autour de 300 (30 par 10).
Le fond peut être une image.
L'image "nuit_etoilee.jpg" a été récupérée sur la toile. Avec Paint j'ai modifié les dimensions pour qu'elles correspondent à celles fenêtre (600 par 400).
Cependant c'est vraiment un jeu basique car les collisions ne sont pas gérées, il n'y a pas de score, pas de son, etc.
Il faut déterminer la position initiale de chaque sprite.
La planète se déplace automatiquement dans la fenêtre de jeu selon un delta de 3 tantôt positif (si gauche vers droite OU si haut vers bas)
et tantôt négatif (si droite vers gauche OU bas vers haut).
Le taux de rafraichissement (FPS) est de 24 images à la seconde (comme un film).
Les deux "sprites" font environ 100 par 100 pixels ; c'est pour cette raison que "limite" est fixée à 500 (600 -100).
Jeu : déplacez avec les touches de direction la fusée pour éviter une collision avec la planète.
Si vous jugez que ça va trop vite, vous pouvez modifier la FPS.
Problème : la fusée peut sortir de la fenêtre ...
Rajoutez en début de programme l'instruction from pygame.locals import * Vous pouvez alors simplifier les instructions relatives aux évènements.
if event.type ==QUIT: boucle_jeu =False if event.type == KEYDOWN : if event.key == K_LEFT : ... if event.key == K_RIGHT : ... if event.key == K_UP : ... if event.key == K_DOWN : ... ...
Donc vous n'avez plus besoin de préfixer les constantes événementielles du terme "pygame."
Jusqu'à présent le fond de la fenêtre était une couleur unie. Mais vous pouvez dessiner des rectangles dans la fenêtre de jeu.
On dit que l'on définit des surfaces.
Remaarque : la commande pygame.quit() est conseillée en fin de script ; c'est l'invers de pygame.init().
Cette instruction ne doit être exécutée qu'une fois et doit donc être située après la boucle de jeu.
Dans le script ci-dessus j'ai utilisé pygame.Surface() pour crée des rectangles remplis d'une couleur unie qui seront
positionnés dans la fenêtre de jeu et qu'on appelle surfaces.
Mais attention la notion de surface est beaucoup plus large : la fenêtre de jeu est une surface, un texte est une surface,
une image chargée est une surface.
Pour positionner une surface "fille" dans une surface "mère" il faut utiliser la commande surface_Mère.blit(surfaceFille, (x,y)).
En général on positionne la surface "fille" dans la fenêtre de jeu , qui se nomme toujours "fenetre" dans mes scripts.
Donc l'instruction devient alors : fenetre.blit(nomSurface, (x,y))
Pour remplir une surface de type rectangle avec une couleur il faut utiliser la commande nomSurface.fill(couleur).
L'argument "couleur" correspond en général à une variable stockant un tuple (code RGB de la couleur).
La fenêtre d'exécution (de l'IDLE) retourne :
type de surface1 : class 'pygame.surface.Surface'
Donc on a créé des instances de la classe pygame.surface.Surface
Seriez vous capable de concevoir une fenêtre de jeu correspondant au drapeau tricolore ?
La notation RGB offre 256 * 256 * 256 couleurs possibles ; c'est énorme !
Des liens utiles :
La notation RGB des 16 couleurs de base
Une application en ligne pour avoir le code RGB d'une couleur
composée via trois curseurs
Le module draw permet de créer des formes géométriques.
Dans tous les cas ces paramètres de position et de taille sont précisés sous forme d'un tuple.
Avant ce tuple, il faut préciser la surface cible et la couleur de remplissage de la forme.
Info affichée dans le shell :
type de polygone : class 'pygame.rect.Rect'
Via la commande draw on crée des objets de type rect ...
Je n'en dis pas plus pour le moment ; j'aurais l'occasion de revenir sur cette notion d'objet de type rect.
Plutôt que d'être dessinée directement dans la fenêtre de jeu, une forme peut être dessinée dans une surface.
On voit bien que les formes de fond rouge et noir sont incluses dans des rectangles de fond blanc.
Bien évidemment dans le cadre d'un jeu il faudrait que les surfaces soient remplies de vert comme la couleur de fond de la fenêtre de jeu.
Infos affichées dans le shell :
type de surface3 : class 'pygame.surface.Surface' type de forme3 : class 'pygame.surface.Surface'
Une forme dessinée dans une surface est confondue avec la surface qui l'accueille.
Vous disposez maintenant de toutes les connaissances pour comprendre le premier script de ce chapitre (premier_jeu.py).
Ainsi vous savez dessiner des rectangles et les animer automatiquement (avec gestion du rebondi) ou déplacer via le clavier.
XR = 200 # abscisse du carré rouge YR = 200 # ordonnée du carré rouge XV = 175 # abscisse du carré vert YV = 400 # ordonnée du carré vert
R comme rouge et V comme vert
# gestion collision entre deux carrés if (abs(XV-XR) < cote) and (abs(YV-YR) < cote) : boucle_jeu = False
En fait c'est très simple ; si l'écart absolu entre les abscisses ET les ordonnées des carrés est inférieur au côté du carré cela signifie qu'il y a chevauchement des deux carrés donc collision.
La variable delta doit alternativement être égal à 3 ou -3.
#gestion rebondissement du carré rouge if XR >= limite : XR = limite delta = -3 elif XR <= 0: XR = 0 delta = 3
Déplacement du carré vert par clavier :
if event.type == pygame.KEYDOWN : if event.key == pygame.K_RIGHT : XV+=ecart # déplacement à droite if event.key ==pygame.K_LEFT: XV-=ecart # déplacement à gauche XR += delta YV -= remontee
Pour que le carré vert reste dans la fenêtre de jeu :
if YV <=0 : YV = 400 XV = 175 if XV <=0 : XV = 0 if XV >= limite: XV = limite
Le meilleur moyen de vérifier si vous avez assimilé et de réaliser une animation pygame :
"la boule rouge rebondissante".
La fenêtre représente en effet un billard et le cercle rouge est une boule.
Je vous communique un extrait du programme. À vous de compléter.
# pygame_test9.py # la boule rebondissante import pygame from pygame.locals import * pygame.init() dimensions =(400,600) rouge = ... vert = ... rayon = 30 limiteX = ... limiteY = ... vitesse = 20 deltaX= 4 deltaY = 6 boucle_jeu = True fenetre = pygame.display.set_mode (...) pygame.display.set_caption(...) clock = ... # coordonnées du centre de la boule en début de jeu CX = 200 CY = 300 # début boucle de jeu while boucle_jeu : clock.tick(vitesse) for event in pygame.event.get(): # boucle de gestion d'évènements if event.type == pygame.QUIT: boucle_jeu = False CX+=... CY+=... #gestion rebondi de la boule rouge if CX >= limiteX: CX = limiteX deltaX = -deltaX if CX <= ... ... ... if CY >= ... ... ... if CY <= ... ... ... fenetre.fill(vert) pygame.draw.circle(...) pygame.display. ... # fin boucle de jeu pygame.quit()
À chaque itération la boule se déplace de 4 pixels sur l'axe X et de 6 pixels sur l'axe Y (deltaX & deltaY)/
La boule ne doit pas sortir de la fenêtre donc CX, CY ne doivent pas être inférieurs à rayon ;
CX ne doit pas être supérieur à limiteX (largeur - rayon) et CY ne doit dépasser limiteY (hauteur - rayon).