5 mini-jeux Pygame étape par étape — Crée, joue, customise !
Tu veux apprendre à créer des jeux rapidement, sans moteur lourd ? Parfait — voici 5 mini-jeux complets et expliqués pas à pas avec Pygame. Chaque jeu est minimal, prêt à lancer et facile à étendre. Je te donne le code, les commandes, les contrôles et des idées d’amélioration. Zéro blabla inutile, que du fun et du concret.
Avant de commencer
Installe Pygame :pip install pygame
Puis sauvegarde chaque script dans un fichier.py
(ex :pong.py
) et exécute-le avecpython pong.py
.
Pong — le classique revisité (niveau : débutant)
But : garder la balle sur ton côté et marquer contre l’IA.
Contrôles
Z
/S
(ouUP
/DOWN
) pour monter/descendre.
Étapes rapides
- Crée fenêtre, paddles, balle.
- Gère mouvement et collisions.
- Ajoute score et reset après but.
Code (copier → lancer)
# pong.py - Pong minimal avec IA simple
import pygame, sys, random
pygame.init()
W, H = 800, 500
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Pong - Mini")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 36)
P_W, P_H = 12, 90
p1 = pygame.Rect(20, H//2 - P_H//2, P_W, P_H)
p2 = pygame.Rect(W-32, H//2 - P_H//2, P_W, P_H)
ball = pygame.Rect(W//2-10, H//2-10, 20, 20)
p_speed = 6
ball_vx, ball_vy = random.choice([-5,5]), random.choice([-3,3])
score1 = score2 = 0
def reset_ball():
global ball_vx, ball_vy
ball.center = (W//2, H//2)
ball_vx = random.choice([-5,5])
ball_vy = random.choice([-4,4])
running = True
while running:
for e in pygame.event.get():
if e.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
if keys[pygame.K_z] or keys[pygame.K_UP]:
p1.y -= p_speed
if keys[pygame.K_s] or keys[pygame.K_DOWN]:
p1.y += p_speed
p1.y = max(0, min(H-P_H, p1.y))
# IA simple : suivre la balle
if p2.centery < ball.centery:
p2.y += 4
else:
p2.y -= 4
p2.y = max(0, min(H-P_H, p2.y))
# Ball movement
ball.x += ball_vx
ball.y += ball_vy
if ball.top <= 0 or ball.bottom >= H:
ball_vy *= -1
if ball.colliderect(p1) or ball.colliderect(p2):
ball_vx *= -1
# Score
if ball.left <= 0:
score2 += 1
reset_ball()
if ball.right >= W:
score1 += 1
reset_ball()
screen.fill((10,10,30))
pygame.draw.rect(screen, (200,200,200), p1)
pygame.draw.rect(screen, (200,200,200), p2)
pygame.draw.ellipse(screen, (255,200,0), ball)
score_text = font.render(f"{score1} - {score2}", True, (200,200,200))
screen.blit(score_text, (W//2 - score_text.get_width()//2, 10))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
Extensions
- Ajouter rebonds angulaires selon la partie du paddle touchée.
- Mode deux joueurs local.
- Power-ups (ball speed up / slow).
Snake — le serpent glouton (niveau : débutant)
But : manger la nourriture, grandir, éviter le mur et ton corps.
Contrôles
- Flèches ou
ZQSD
selon ton clavier.
Principes
- Grille régulière (taille bloc) pour simplifier la logique.
- Corps = liste de segments.
Code
# snake.py - version simple
import pygame, sys, random
pygame.init()
W, H = 600, 400
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Snake - Mini")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 36)
BLOCK = 20
def rnd():
return random.randrange(0, W, BLOCK), random.randrange(0, H, BLOCK)
snake = [(BLOCK*5, BLOCK*5), (BLOCK*4, BLOCK*5)]
dx, dy = BLOCK, 0
food = rnd()
score = 0
running = True
while running:
for e in pygame.event.get():
if e.type == pygame.QUIT: running = False
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_LEFT and dx == 0:
dx, dy = -BLOCK, 0
if e.key == pygame.K_RIGHT and dx == 0:
dx, dy = BLOCK, 0
if e.key == pygame.K_UP and dy == 0:
dx, dy = 0, -BLOCK
if e.key == pygame.K_DOWN and dy == 0:
dx, dy = 0, BLOCK
head = (snake[0][0] + dx, snake[0][1] + dy)
snake.insert(0, head)
if head == food:
score += 1
while True:
food = rnd()
if food not in snake: break
else:
snake.pop()
# Collisions
if (head[0] < 0 or head[0] >= W or head[1] < 0 or head[1] >= H or head in snake[1:]):
print("Game Over. Score:", score)
running = False
screen.fill((0,0,0))
for seg in snake:
pygame.draw.rect(screen, (50,200,50), (*seg, BLOCK, BLOCK))
pygame.draw.rect(screen, (200,50,50), (*food, BLOCK, BLOCK))
score_surf = font.render(f"Score: {score}", True, (255,255,255))
screen.blit(score_surf, (10,10))
pygame.display.flip()
clock.tick(10)
pygame.quit()
sys.exit()
Extensions
- Portails, murs aléatoires, niveaux de vitesse progressifs, pause & save.
Breakout / Casse-briques (niveau : intermédiaire)
But : casser toutes les briques avec une balle qui rebondit sur ta raquette.
Contrôles
- Gauche/Droite ou souris pour déplacer la raquette.
Notes
- Liste de briques = liste de
pygame.Rect
, on supprime à la collision.
Code
# breakout.py - Casse-briques minimal
import pygame, sys, random
pygame.init()
W, H = 640, 480
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Breakout - Mini")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 30)
paddle = pygame.Rect(W//2-60, H-30, 120, 12)
ball = pygame.Rect(W//2-8, H-50, 16, 16)
ball_vx, ball_vy = 4, -4
# Create bricks
rows, cols = 5, 8
brick_w = W // cols
bricks = []
for r in range(rows):
for c in range(cols):
rect = pygame.Rect(c*brick_w + 2, 40 + r*25, brick_w-4, 20)
bricks.append(rect)
running = True
lives = 3
while running:
for e in pygame.event.get():
if e.type == pygame.QUIT: running = False
mx = pygame.mouse.get_pos()[0]
paddle.x = mx - paddle.width//2
paddle.x = max(0, min(W-paddle.width, paddle.x))
ball.x += ball_vx; ball.y += ball_vy
if ball.left <= 0 or ball.right >= W:
ball_vx *= -1
if ball.top <= 0:
ball_vy *= -1
if ball.colliderect(paddle):
ball_vy *= -1
# add angle based on hit position
offset = (ball.centerx - paddle.centerx) / (paddle.width/2)
ball_vx = int(offset * 6)
# Brick collision
hit_index = ball.collidelist(bricks)
if hit_index != -1:
hit = bricks.pop(hit_index)
ball_vy *= -1
if ball.bottom >= H:
lives -= 1
ball.center = (W//2, H-60)
ball_vx, ball_vy = random.choice([-4,4]), -4
if lives <= 0:
print("Game Over")
running = False
screen.fill((12,12,40))
pygame.draw.ellipse(screen, (255,200,0), ball)
pygame.draw.rect(screen, (200,200,200), paddle)
for b in bricks:
pygame.draw.rect(screen, (100,180,240), b)
txt = font.render(f"Lives: {lives} Bricks: {len(bricks)}", True, (255,255,255))
screen.blit(txt, (10,10))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
Extensions
- Power-ups qui élargissent la raquette, balles multiples, niveaux.
Flappy-like (niveau : intermédiaire)
But : éviter les tuyaux en tapotant pour sauter.
Contrôles
SPACE
pour sauter.
Principes
- Gravité, impulsion de saut, tuyaux générés à intervalle régulier.
Code
# flappy.py - clone basique
import pygame, sys, random
pygame.init()
W, H = 400, 600
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Flappy Mini")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 36)
x = 60
y = H//2
vel = 0
gravity = 0.6
jump = -10
pipes = []
SPAWN = pygame.USEREVENT + 1
pygame.time.set_timer(SPAWN, 1400)
gap = 140
speed = 3
score = 0
running = True
while running:
for e in pygame.event.get():
if e.type == pygame.QUIT: running = False
if e.type == pygame.KEYDOWN and e.key == pygame.K_SPACE:
vel = jump
if e.type == SPAWN:
h = random.randint(100, H-200)
pipes.append([W, h])
vel += gravity
y += vel
for p in pipes:
p[0] -= speed
# remove offscreen & score
if pipes and pipes[0][0] < -100:
pipes.pop(0)
score += 1
# Collision
bird_rect = pygame.Rect(x-18, int(y)-18, 36, 36)
for p in pipes:
top = pygame.Rect(p[0], 0, 60, p[1])
bot = pygame.Rect(p[0], p[1]+gap, 60, H - (p[1]+gap))
if bird_rect.colliderect(top) or bird_rect.colliderect(bot):
print("Game Over! Score:", score)
running = False
if y <= 0 or y >= H:
print("Game Over! Score:", score)
running = False
screen.fill((80,200,250))
# draw bird
pygame.draw.circle(screen, (255,220,0), (x, int(y)), 18)
# pipes
for p in pipes:
pygame.draw.rect(screen, (40,160,40), (p[0], 0, 60, p[1]))
pygame.draw.rect(screen, (40,160,40), (p[0], p[1]+gap, 60, H - (p[1]+gap)))
score_s = font.render(str(score), True, (255,255,255))
screen.blit(score_s, (W//2 - score_s.get_width()//2, 20))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
Extensions
- Ajoute animations, sons, effet de rotation de l’oiseau, tableau des meilleurs scores.
Memory / Jeu des paires (niveau : intermédiaire)
But : retrouver toutes les paires en retournant deux cartes à la fois.
Contrôles
- Clique gauche pour retourner une carte.
Principes
- Grille 4×4, paires de valeurs mélangées, délai pour retourner si différent.
Code
# memory.py - Memory (paires)
import pygame, sys, random, time
pygame.init()
W, H = 480, 480
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("Memory - Mini")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 36)
ROWS, COLS = 4, 4
CARD_W = W // COLS
values = list(range((ROWS*COLS)//2)) * 2
random.shuffle(values)
# state arrays
revealed = [False] * (ROWS*COLS)
matched = [False] * (ROWS*COLS)
first = second = -1
lock_time = 0
def idx_from_pos(mx, my):
c = mx // CARD_W
r = my // CARD_W
return r*COLS + c
running = True
while running:
for e in pygame.event.get():
if e.type == pygame.QUIT: running = False
if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
if lock_time and time.time() < lock_time:
continue
mx, my = e.pos
i = idx_from_pos(mx, my)
if matched[i] or revealed[i]: continue
if first == -1:
first = i; revealed[i] = True
elif second == -1:
second = i; revealed[i] = True
if values[first] == values[second]:
matched[first] = matched[second] = True
first = second = -1
else:
lock_time = time.time() + 0.8 # show for 0.8s
# unlock after delay
if lock_time and time.time() > lock_time:
revealed[first] = revealed[second] = False
first = second = -1
lock_time = 0
screen.fill((30,30,40))
for i in range(ROWS*COLS):
r, c = divmod(i, COLS)
rect = pygame.Rect(c*CARD_W+6, r*CARD_W+6, CARD_W-12, CARD_W-12)
if revealed[i] or matched[i]:
txt = font.render(str(values[i]), True, (10,10,10))
pygame.draw.rect(screen, (200,200,200), rect)
screen.blit(txt, (rect.x + rect.w//2 - txt.get_width()//2, rect.y + rect.h//2 - txt.get_height()//2))
else:
pygame.draw.rect(screen, (80,120,200), rect)
if all(matched):
w = font.render("Bravo ! Tu as gagné.", True, (255,255,255))
screen.blit(w, (W//2 - w.get_width()//2, H//2 - 20))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
Extensions
- Remplacer les nombres par des images (cartes), ajouter timer, niveaux de difficulté (taille grille).
Conseils pratiques (pour tous les jeux)
- Pas d’assets ? Dessine avec
pygame.draw.*
— c’est suffisant pour un prototype. - Sons :
pygame.mixer.Sound("ping.wav")
→ joue un effet. - FPS : règle
clock.tick()
pour ajuster la difficulté. - Organisation : sépare les fichiers (assets, utils, niveaux) quand ton projet grandit.
- Versionnage : utilise Git dès le début — tu remercieras ton futur toi.
Idées pour aller plus loin (freelance / portfolio)
- Pack plusieurs mini-jeux dans un launcher + menu, sauvegarde du score → beau projet portfolio.
- Prototypage rapide d’un jeu éducatif pour écoles (quiz gamifié).
- Atelier “game jam” : adapte un des jeux en 48h et propose-le sur Itch.io.
Licence & assets
Tous les scripts ci-dessus sont libres pour usage personnel et apprentissage. Si tu utilises des images ou sons externes, vérifie les licences (Creative Commons, domaine public, ou crée-les toi-même).
Conclusion
Créer des mini-jeux avec Python et Pygame est une excellente façon d’apprendre à programmer tout en s’amusant. Que ce soit avec Pong, Snake ou encore un petit Flappy, chaque projet t’aide à développer ta logique, ta créativité et tes compétences techniques pas à pas.
Et si tu veux aller encore plus loin, sache qu’il est même possible de gagner de l’argent avec Python grâce à tes compétences. Pour découvrir comment, je t’invite à lire cet article 👉 Comment gagner de l’argent avec Python.