Pygame : code un jeu d'esquive en Python, jouable en 60 lignes

De quoi avez-vous besoin

Version de Python

3.x

Packages

  • {"nom": "pygame", "version": "2.6.x"}

Difficulté

Débutant

Unity, Unreal, Godot... quand on parle de jeu vidéo, on imagine tout de suite un gros moteur, des scènes 3D et un éditeur qui occupe trois écrans. La réalité, c'est qu'un jeu d'arcade — celui qui tourne dans une simple fenêtre, avec un carré qui se déplace et des obstacles qui tombent — tient dans un seul fichier Python. Pygame, la bibliothèque de jeux la plus installée de l'écosystème Python, s'en charge depuis plus de vingt ans.

Pygame n'est pas un moteur de jeu. C'est une couche au-dessus de SDL, la bibliothèque C qui gère les fenêtres, le clavier, la souris et le son sur Windows, macOS et Linux. Tu écris la boucle de jeu toi-même, à la main. C'est justement ce qui la rend précieuse : tu comprends ce qui se passe à chaque image, et rien ne t'est caché. Dans ce tutoriel, tu vas coder un jeu d'esquive — un carré vert que tu déplaces avec les flèches, des carrés rouges qui tombent du ciel, un score qui grimpe et une collision qui met fin à la partie. Le tout en une soixantaine de lignes.

Installer Pygame et ouvrir une fenêtre

Commence par installer Pygame dans ton environnement :

python
pip install pygame

Puis pose le squelette de tout jeu vidéo : l'initialisation, la fenêtre et la boucle de jeu. Cette boucle est le cœur battant du programme. Elle tourne en continu : elle lit les événements, met à jour l'état du jeu et redessine l'écran, des dizaines de fois par seconde.

python
import pygame

pygame.init()
fenetre = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Esquive !")

en_cours = True
while en_cours:
    for evenement in pygame.event.get():
        if evenement.type == pygame.QUIT:
            en_cours = False

pygame.quit()

Le `pygame.event.get()` vide la file d'événements. Sans lui, ta fenêtre se fige, parce que le système d'exploitation croit que le programme ne répond plus. L'événement `pygame.QUIT` se déclenche quand on clique sur la croix rouge. C'est lui qui fait sortir la boucle proprement.

Le joueur et le clavier

Dans Pygame, un personnage, c'est un `pygame.Rect` : un rectangle défini par sa position (x, y) et sa taille. On le dessine avec `pygame.draw.rect`. Pour le déplacer, on lit l'état du clavier avec `pygame.key.get_pressed()`, qui renvoie un tableau où chaque touche vaut Vrai si elle est enfoncée.

python
import pygame

pygame.init()
LARGEUR, HAUTEUR = 600, 400
fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption("Esquive !")
horloge = pygame.time.Clock()

joueur = pygame.Rect(280, HAUTEUR - 60, 40, 40)

en_cours = True
while en_cours:
    for evenement in pygame.event.get():
        if evenement.type == pygame.QUIT:
            en_cours = False

    touches = pygame.key.get_pressed()
    if touches[pygame.K_LEFT] and joueur.left > 0:
        joueur.x -= 5
    if touches[pygame.K_RIGHT] and joueur.right < LARGEUR:
        joueur.x += 5

    fenetre.fill((20, 20, 40))
    pygame.draw.rect(fenetre, (0, 200, 120), joueur)
    pygame.display.flip()
    horloge.tick(60)

pygame.quit()

Trois nouveautés à retenir : `fenetre.fill` repeint le fond à chaque image, sinon le carré laisse une traînée derrière lui. `pygame.display.flip()` affiche ce qu'on vient de dessiner. Et `horloge.tick(60)` cale la boucle sur 60 images par seconde, pour que le jeu ait la même vitesse sur n'importe quel PC. Les conditions `joueur.left > 0` et `joueur.right < LARGEUR` empêchent le carré de sortir de l'écran.

Les obstacles qui tombent

Pour les obstacles, on garde une liste de `Rect`. Toutes les 30 images, on en crée un en haut de la fenêtre, à une position horizontale tirée au hasard avec `random.randint`. Ensuite, on les fait descendre, et on supprime ceux qui sortent par le bas.

python
import pygame
import random

pygame.init()
LARGEUR, HAUTEUR = 600, 400
fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption("Esquive !")
horloge = pygame.time.Clock()

joueur = pygame.Rect(280, HAUTEUR - 60, 40, 40)
obstacles = []
compteur = 0

en_cours = True
while en_cours:
    for evenement in pygame.event.get():
        if evenement.type == pygame.QUIT:
            en_cours = False

    touches = pygame.key.get_pressed()
    if touches[pygame.K_LEFT] and joueur.left > 0:
        joueur.x -= 5
    if touches[pygame.K_RIGHT] and joueur.right < LARGEUR:
        joueur.x += 5

    compteur += 1
    if compteur >= 30:
        obstacles.append(pygame.Rect(random.randint(0, LARGEUR - 30), -30, 30, 30))
        compteur = 0

    for obstacle in obstacles[:]:
        obstacle.y += 7
        if obstacle.top > HAUTEUR:
            obstacles.remove(obstacle)

    fenetre.fill((20, 20, 40))
    pygame.draw.rect(fenetre, (0, 200, 120), joueur)
    for obstacle in obstacles:
        pygame.draw.rect(fenetre, (230, 60, 60), obstacle)
    pygame.display.flip()
    horloge.tick(60)

pygame.quit()

Le détail qui compte : on parcourt `obstacles[:]`, une copie de la liste, pas `obstacles` directement. Modifier une liste pendant qu'on la parcourt, c'est le meilleur moyen de sauter des éléments ou de faire planter le script. Le `random.randint(0, LARGEUR - 30)` garantit que l'obstacle, large de 30 pixels, tient entièrement dans la fenêtre.

Score, collision et fin de partie

Il ne reste que deux choses : afficher le score et détecter la collision. Pour le texte, `pygame.font.Font(None, 36)` crée une police, `render` transforme la chaîne en surface, et `blit` la colle sur la fenêtre. Pour la collision, `joueur.colliderect(obstacle)` renvoie Vrai dès que les deux rectangles se chevauchent. Voici le jeu complet :

python
import pygame
import random

pygame.init()
LARGEUR, HAUTEUR = 600, 400
fenetre = pygame.display.set_mode((LARGEUR, HAUTEUR))
pygame.display.set_caption("Esquive !")
horloge = pygame.time.Clock()
police = pygame.font.Font(None, 36)

joueur = pygame.Rect(280, HAUTEUR - 60, 40, 40)
obstacles = []
compteur = 0
score = 0

en_cours = True
while en_cours:
    for evenement in pygame.event.get():
        if evenement.type == pygame.QUIT:
            en_cours = False

    touches = pygame.key.get_pressed()
    if touches[pygame.K_LEFT] and joueur.left > 0:
        joueur.x -= 5
    if touches[pygame.K_RIGHT] and joueur.right < LARGEUR:
        joueur.x += 5

    compteur += 1
    if compteur >= 30:
        obstacles.append(pygame.Rect(random.randint(0, LARGEUR - 30), -30, 30, 30))
        compteur = 0

    for obstacle in obstacles[:]:
        obstacle.y += 7
        if obstacle.top > HAUTEUR:
            obstacles.remove(obstacle)
            score += 1

    for obstacle in obstacles:
        if joueur.colliderect(obstacle):
            en_cours = False

    fenetre.fill((20, 20, 40))
    pygame.draw.rect(fenetre, (0, 200, 120), joueur)
    for obstacle in obstacles:
        pygame.draw.rect(fenetre, (230, 60, 60), obstacle)
    texte = police.render(f"Score : {score}", True, (255, 255, 255))
    fenetre.blit(texte, (10, 10))
    pygame.display.flip()
    horloge.tick(60)

pygame.quit()
print(f"Partie terminée. Score final : {score}")

Enregistre ce code dans un fichier `esquive.py` et lance-le avec `python esquive.py`. Les flèches gauche et droite déplacent le carré vert, le score monte à chaque obstacle esquivé, et la partie s'arrête au premier carré rouge touché. Le score final s'affiche dans le terminal.

Et après ?

Tu viens de coder un jeu complet : fenêtre, clavier, objets, collision, score, fin de partie. Ce sont les briques de n'importe quel jeu d'arcade. À partir de là, tu peux accélérer la chute des obstacles quand le score grimpe, sauvegarder le meilleur score dans un fichier, ajouter des images et des sons avec `pygame.image.load` et `pygame.mixer`, ou un bouton pour rejouer. Tu peux aussi brancher ce que tu sais déjà de l'IA : entraîner un agent qui déplace le carré tout seul, en réutilisant tes parties comme données d'entraînement.

Le plus important, c'est ce que tu as compris en écrivant la boucle : un jeu vidéo, au fond, c'est une fonction qui lit les entrées, met à jour un état et redessine l'écran, soixante fois par seconde. Le reste, c'est du détail — et du détail, tu sais maintenant en ajouter.

K

Auteur

Krugz

Développeur fullstack

Développeur fullstack qui tente, tant bien que mal, de suivre l'actualité de l'IA au milieu d'une marée d'informations imbuvables et des milliers d'outils et de modèles qui sortent chaque jour.