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 :
pip install pygamePuis 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.
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.
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.
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 :
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.
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.






