Sessions
Choisis une série ci-dessous. Les sessions Python construisent des jeux avec Pygame. Les sessions Git t’apprennent la gestion de versions : de ton premier commit aux pull requests.
Choisis une série ci-dessous. Les sessions Python construisent des jeux avec Pygame. Les sessions Git t’apprennent la gestion de versions : de ton premier commit aux pull requests.
Dix sessions dans lesquelles tu construis chaque mois un jeu Pygame complet. Chaque session contient une fiche de travail, un cheatsheet et du code de départ à télécharger.
draw()/update() et tu déplaces un sprite avec les flèches.pygame.Rect, tu fais rebondir la balle en inversant sa vitesse et tu tiens le score pour deux joueurs.pygame.mixer et tu construis un écran de victoire et de défaite.vel_y et tu détectes les collisions avec les plateformes grâce à pygame.Rect.__init__ et tu crées une sous-classe par héritage.Dans cette session, tu construis un mini-jeu : une étoile tombe et toi, tu l’attrapes avec un panier. À la fin de la session, tout bouge, le jeu compte combien d’étoiles tu attrapes et tu as ton premier jeu à toi.
draw() : ce que tu dessines à chaque frameupdate() : ce qui change à chaque framemain.py dans Thonny.La fonction update() tourne 60 fois par seconde. Tout ce que tu y mets est donc exécuté 60 fois par seconde. C’est comme ça que le mouvement fonctionne dans un jeu.
Pour l’instant, il n’y a que pass dans update(). Ça veut dire « ne fais rien ». Supprime pass et ajoute ceci :
def update():
star.y = star.y + 3Clique sur Run. L’étoile tombe maintenant du haut vers le bas. Quand elle sort de l’écran, elle disparaît. On va régler ça.
Que se passe-t-il ici ? star.y est la position verticale de l’étoile. Plus y est grand, plus l’étoile est bas sur l’écran. En ajoutant + 3 à chaque frame, l’étoile descend petit à petit.
Le système de coordonnées : (0, 0) se trouve en haut à gauche, pas en bas à gauche comme en maths. x va vers la droite, y va vers le bas. L’étoile commence à y = 30 (presque tout en haut), le panier est à y = 370 (presque tout en bas).
Bouge ta souris sur l’écran ci-dessous pour voir les coordonnées :
Bouge ta souris sur l'écran pour voir les coordonnées.
Tu veux en savoir plus sur le fonctionnement de l’écran ? → Les coordonnées expliquées
Bouge les curseurs et regarde comment actor.x et actor.y changent quand l’actor se déplace :
C’est le moment de piloter le panier. Pygame Zero a une variable pratique, keyboard, qui garde la trace des touches pressées.
Ajoute ceci dans update(), après la ligne de l’étoile :
def update():
star.y = star.y + 3
if keyboard.left:
basket.x = basket.x - 5
if keyboard.right:
basket.x = basket.x + 5Clique sur Run et utilise les flèches. Le panier bouge avec toi !
Astuce (facultatif, compte comme Stretch) : Si tu pousses le panier trop à gauche ou trop à droite, il disparaît de l’écran. Tu peux ajouter un test qui évite ça ? Indice : utilise WIDTH et compare avec basket.x.
Maintenant, tu veux que quelque chose se passe quand le panier touche l’étoile. Pour ça, tu utilises colliderect. Il vérifie si deux rectangles se chevauchent.
Ajoute ceci dans update() :
if star.colliderect(basket):
star.y = 0L’étoile remonte quand tu l’attrapes. Mais et si tu la rates ? Ajoute aussi ceci :
if star.y > HEIGHT:
star.y = 0Bonus : Fais réapparaître l’étoile à un endroit au hasard chaque fois. Ajoute en haut du fichier :
import randomRemplace ensuite star.y = 0 (aux deux endroits) par :
star.x = random.randint(20, WIDTH - 20)
star.y = 0Maintenant, l’étoile tombe chaque fois à un autre endroit. Bien plus difficile à attraper !
Un vrai jeu garde la trace de ton score. Pour ça, tu as besoin d’une variable qui vit en dehors des fonctions : une variable globale.
Clique sur le bouton ci-dessous pour voir comment score change chaque fois que tu attrapes une étoile :
Ajoute ceci tout en haut, en dehors de toutes les fonctions (après les lignes de basket et star) :
score = 0Dans draw(), ajoute :
screen.draw.text(f"Score: {score}", topleft=(10, 10), color="white")Dans update(), adapte le code de l’attrape pour que le score monte :
if star.colliderect(basket):
global score
score = score + 1
star.x = random.randint(20, WIDTH - 20)
star.y = 0global score dit à Python : « je parle du score d’en dehors de cette fonction, pas d’une nouvelle variable locale. » Sans cette ligne, tu obtiens une erreur.
Clique sur Run. Le score est en haut à gauche et augmente chaque fois que tu attrapes une étoile !
Montre ton jeu à un coach et à un buddy. Raconte ce que tu as fait : ce qui marche et ce que tu as ajouté en plus.
« La prochaine fois : des trucs qui RÉPLIQUENT. Et ça fait BOUM, avec un vrai son. »
Essaie une de ces extensions à la maison. Chacune a un indice de code pour te lancer.
Limite les vies — Ajoute levens = 3. En cas de raté (star.y > HEIGHT) : levens -= 1. Arrête le jeu quand levens == 0 avec game_over = True et affiche « Game Over » dans draw().
Couleur d’étoile aléatoire — À chaque attrape : donne une nouvelle couleur à l’étoile avec random.randint(50, 255) pour le rouge, le vert et le bleu. Commence à 50, pas à 0 — sinon l’étoile est parfois noire et invisible.
Arrière-plan — Dessine des étoiles fixes en arrière-plan dans draw(), avant le score. Utilise screen.draw.filled_circle(x, y, 2, "white") à 20 positions au hasard. Fais random.seed(42) pour qu’elles ne clignotent pas.
Deuxième étoile — Fais sterren = [star, Actor("star")]. Donne à chaque étoile son propre x. Mets-les à jour toutes les deux dans update() et dessine-les dans draw().
Meilleur score — Garde high_score. Si score > high_score : high_score = score. Affiche f"Meilleur : {high_score}" à côté du score.
Panier plus petit — Tous les 5 points : basket.width = max(30, basket.width - 5). Remets basket.width à sa valeur au redémarrage.
Bombe — Ajoute un cercle rouge qui tombe de temps en temps. Utilise un timer bom_timer et random.randint pour décider quand il apparaît. Si le panier touche la bombe : score -= 2.
Niveau de difficulté — Tous les 5 étoiles : augmente la vitesse de chute de 1. Prévois un maximum : max(3, star_snelheid).
Ton vaisseau flotte dans l’espace sombre pendant que des météores arrivent du haut vers le bas. Évite-les, ou perds une vie. Plus tu survis longtemps, plus ils vont vite. Et cette fois, tu construis aussi Dojo Defender : le plus grand projet qui grandit à chaque session.
main.py.Complète la fonction spawn_meteor(). Un météore est un Actor qui commence en haut de l’écran à une position x au hasard :
import random
def spawn_meteor():
rock = Actor('meteor')
rock.x = 0
rock.y = random.randint(30, WIDTH - 30)
meteors.append(rock)Appelle la fonction dans update(), mais pas à chaque frame, sinon l’écran se remplit d’un coup. La fonction update() tourne 60 fois par seconde. Utilise ça pour tenir un compteur :
Regarde ci-dessous à quelle vitesse un météore se déplace selon la vitesse, et combien de pixels ça fait par seconde :
Utilise un compteur :
# en haut, en dehors des fonctions :
timer = 0
def update():
global timer
timer += 1
if timer % 60 == 0: # chaque seconde (60 frames)
spawn_meteor()Clique sur Run. Après une seconde, le premier météore apparaît, mais il ne bouge pas encore.
Fais descendre tous les météores de la liste, et supprime-les quand ils sortent de l’écran :
def update():
global timer
timer += 1
if timer % 60 == 0:
spawn_meteor()
for rock in meteors[:]: # [:] = une copie pour pouvoir supprimer sans risque
rock.y += 4
if rock.y > HEIGHT + 30:
meteors.remove(rock)Détecter une collision : Si un météore touche le vaisseau, tu perds une vie. Ajoute ceci dans la boucle :
if rock.colliderect(ship):
meteors.remove(rock)
global lives
lives -= 1
if lives <= 0:
# TODO : game over (étape 3)
passGame over : Ajoute une variable game_over = False en haut. Si lives == 0, mets game_over = True. Dans draw(), affiche un texte quand game_over vaut True :
if game_over:
screen.draw.text(
"GAME OVER",
center=(WIDTH / 2, HEIGHT / 2),
color="red",
fontsize=60,
)Arrête le mouvement dans update() quand game_over vaut True :
def update():
if game_over:
return
...Augmenter la vitesse : Fais aller les météores plus vite à mesure que le score monte :
snelheid = 3 + score // 5 # tous les 5 points, +1 de vitesse
rock.y += snelheidScore : Chaque seconde que tu survis, +1 point. Ajoute global score et augmente dans update() :
if timer % 60 == 0:
global score
score += 1
spawn_meteor()Plusieurs tailles : Fais des petits, des moyens et des grands météores. Utilise une variable schaal et adapte la hitbox :
def spawn_meteor():
rock = Actor('meteor')
rock.x = random.randint(30, WIDTH - 30)
rock.y = 0
rock.schaal = random.choice([0.5, 1.0, 1.5])
meteors.append(rock)Les petits météores vont plus vite ; les grands sont plus difficiles à éviter mais rapportent plus de points.
Télécharge le starter Dojo Defender d’aujourd’hui. C’est la base du projet qui grandit à chaque session. Ajoute aujourd’hui ton vaisseau et fais-le bouger avec les flèches.
Tu n’étais pas là la dernière fois ? Pas de problème — télécharge la solution de la dernière fois et tu peux suivre tout de suite.
La fiche de travail complète de Dojo Defender se trouve sur la page Dojo Defender.
Montre ton jeu à un coach et à un buddy. Combien de temps tu survis ? Qui fait le meilleur score ?
« La prochaine fois : ton propre vaisseau RÉPLIQUE. Des ennemis en formation, et c’est toi qui les exploses. »
sounds/hit.wav).Les ennemis sont en formation en haut de l’écran. Toi, tu es en bas avec un vaisseau et un seul objectif : les éliminer tous avant qu’ils atteignent le fond. Appuie sur ESPACE pour tirer, et ne rate pas.
main.py.Le vaisseau bouge déjà avec les flèches. Vérifie le code dans update(). Fais en sorte que le vaisseau ne sorte pas de l’écran :
if keyboard.left and ship.x > 30:
ship.x -= 5
if keyboard.right and ship.x < WIDTH - 30:
ship.x += 5Complète la fonction shoot(). Un projectile est un Actor qui commence à la position du vaisseau :
def shoot():
kogel = Actor('bullet')
kogel.x = ship.x
kogel.y = ship.y - 20
bullets.append(kogel)Appelle shoot() quand la barre d’espace est pressée. Utilise on_key_down (style Pgzero) :
def on_key_down(key):
if key == keys.SPACE:
shoot()Fais monter les projectiles dans update() et supprime-les quand ils sortent de l’écran :
for kogel in bullets[:]:
kogel.y -= 8
if kogel.y < -10:
bullets.remove(kogel)colliderect vérifie si la hitbox rectangulaire de deux actors se chevauche. Bouge ta souris sur l’écran ci-dessous pour voir quand ça arrive :
Vérifie dans update() si un projectile touche un ennemi :
for kogel in bullets[:]:
kogel.y -= 8
if kogel.y < -10:
bullets.remove(kogel)
continue
for vijand in enemies[:]:
if kogel.colliderect(vijand):
bullets.remove(kogel)
enemies.remove(vijand)
global score
score += 10
breakCondition de victoire : Si enemies est vide, tu as gagné :
if not enemies:
screen.draw.text("TU GAGNES !", center=(WIDTH/2, HEIGHT/2), color="yellow", fontsize=60)Fais descendre les ennemis lentement. Utilise un timer :
vijand_timer = 0
def update():
global vijand_timer
vijand_timer += 1
if vijand_timer % 90 == 0: # toutes les 1,5 seconde
for vijand in enemies:
vijand.y += 20Game over quand un ennemi atteint le fond :
for vijand in enemies:
if vijand.y > HEIGHT - 30:
global game_over
game_over = TrueTirer plus vite : Prévois un cooldown pour que le ninja ne puisse pas tirer à l’infini :
shoot_cooldown = 0
def update():
global shoot_cooldown
if shoot_cooldown > 0:
shoot_cooldown -= 1
def on_key_down(key):
global shoot_cooldown
if key == keys.SPACE and shoot_cooldown == 0:
shoot()
shoot_cooldown = 15Montre ton jeu à un coach. En combien de temps tu élimines tous les ennemis ? Compare ton score avec un buddy.
« La prochaine fois : deux joueurs, une balle : PONG. Et tu apprends le vrai pygame, sans pgzrun. »
Regarde le cheatsheet de cette session
Télécharge le starter Dojo Defender d’aujourd’hui.
Tu n’étais pas là la dernière fois ? Télécharge la solution de la session 1 et commence avec ça.
La fiche de travail complète : Dojo Defender Session 2.
Deux raquettes, une balle : le Pong classique. Mais il y a une surprise : dans cette session, tu écris le jeu en vrai pygame, sans pgzrun. Tu apprends à installer toi-même la game loop. C’est comme ça que marchent la plupart des vrais jeux.
pygame.Rect pour les rectangles et les collisionsmain.py.Différence avec pgzrun : il n’y a plus de fonctions draw() et update(). Tout est dans une seule boucle while running:.
Cherche les lignes :
# bal.x += ball_dx # active ceci quand tu as fini
# ball.y += ball_dySupprime le # devant les deux lignes. Mais règle d’abord une vitesse de départ. Cherche ball_dx, ball_dy = 0, 0 et remplace par :
ball_dx, ball_dy = 4, 4Clique sur Run. La balle bouge maintenant, mais elle disparaît par le bord. On règle ça à l’étape 2.
Ajoute ceci après ball.x += ball_dx et ball.y += ball_dy :
# Rebondir sur le bord supérieur et inférieur
if ball.top <= 0 or ball.bottom >= HEIGHT:
ball_dy = -ball_dy
# Rebondir sur les raquettes
if ball.colliderect(left_paddle) or ball.colliderect(right_paddle):
ball_dx = -ball_dxLa balle rebondit maintenant à l’infini. Ajoute aussi des limites pour les raquettes pour qu’elles ne sortent pas de l’écran. Regarde le code qui est déjà dans le starter.
Si la balle sort à gauche, le joueur de droite marque. Si elle sort à droite, c’est celui de gauche :
# Balle sortie à gauche → la droite marque
if ball.left <= 0:
score_right += 1
ball.center = (WIDTH // 2, HEIGHT // 2)
ball_dx = 4
# Balle sortie à droite → la gauche marque
if ball.right >= WIDTH:
score_left += 1
ball.center = (WIDTH // 2, HEIGHT // 2)
ball_dx = -4Le score s’affiche déjà dans draw(). Vérifie que les variables sont correctes.
Gagner à 5 points : ajoute une variable won. Quand un joueur atteint 5, arrête le jeu :
if score_left >= 5:
won = "La gauche gagne !"
if score_right >= 5:
won = "La droite gagne !"Affiche le gagnant à l’écran et arrête le mouvement.
Vitesse qui augmente : après chaque échange, la balle devient un peu plus rapide :
if ball.colliderect(left_paddle) or ball.colliderect(right_paddle):
ball_dx = -ball_dx * 1.05 # 5 % plus rapide
ball_dy = ball_dy * 1.05Prévois un maximum : ball_dx = max(-12, min(12, ball_dx)).
Joue une partie contre un buddy. Le premier à 5 points gagne. Montre-le à un coach.
« La prochaine fois : Breakout. La balle casse des briques. Et il y a du SON. »
Aujourd’hui, Dojo Defender passe au vrai Pygame ! Télécharge le starter. Tu n’étais pas là ? Télécharge la solution de la session 2. Fiche de travail : Dojo Defender Session 3.
Une balle rebondit dans tous les sens et casse des rangées de briques colorées. Tu contrôles la raquette pour garder la balle en l’air. Et cette fois, tu l’entends aussi : il y a des effets sonores à chaque collision.
pygame.mixermain.py.Cherche cette ligne dans le starter :
ball_dx, ball_dy = 4, 0
# ball_dy = -4 ← supprime le # pour faire bouger la balle !Supprime le # devant ball_dy = -4. La balle a maintenant une vitesse verticale. Ajoute le mouvement dans la game loop (cherche la section update) :
ball.x += ball_dx
ball.y += ball_dyClique sur Run. La balle bouge en diagonale mais disparaît par les bords.
Ajoute les rebonds :
# Bord supérieur, gauche et droit
if ball.left <= 0 or ball.right >= WIDTH:
ball_dx = -ball_dx
if ball.top <= 0:
ball_dy = -ball_dy
# Raquette
if ball.colliderect(paddle):
ball_dy = -ball_dy
if snd_hit:
snd_hit.play()Vies : si la balle atteint le bas, tu perds une vie :
if ball.top > HEIGHT:
levens -= 1
# Remets la balle au-dessus de la raquette
ball.center = (paddle.centerx, paddle.top - BALL_SIZE)
ball_dy = -4Vérifie la collision avec chaque brique dans la boucle :
for steen in stenen[:]:
if ball.colliderect(steen['rect']):
stenen.remove(steen)
ball_dy = -ball_dy
score += 10
if snd_hit:
snd_hit.play()
break # casser une seule brique par frameCondition de victoire : si toutes les briques sont parties, le ninja a gagné. Affiche un message :
if not stenen:
# affiche l'écran de victoireSon d’explosion quand une brique casse (utilise snd_explode du starter) :
if snd_explode:
snd_explode.play()Game over à 0 vie : affiche un écran et arrête la balle.
Vitesse qui augmente à mesure qu’il reste moins de briques :
snelheid_factor = 1 + (1 - len(stenen) / totaal_stenen) * 0.5
ball_dx_huidig = ball_dx * snelheid_factorUne nouvelle rangée de briques quand tout est parti : rappelle stenen = maak_stenen() et augmente la difficulté.
Qui enlève le plus de briques ? Compare les scores et montre à ton coach ta plus longue série.
« La prochaine fois : la gravité. Ton personnage tombe, et c’est à toi de le faire sauter de plateforme en plateforme. »
Regarde le cheatsheet de cette session
Dojo Defender reçoit un menu et de nouveaux types d’ennemis ! Télécharge le starter. Tu n’étais pas là ? Télécharge la solution de la session 3. Fiche de travail : Dojo Defender Session 4.
Dans cette session, tu construis un micro-platformer. Ton personnage a de la gravité, peut sauter et ramasse des étoiles sur les plateformes. Pour la première fois, tu utilises pygame directement, sans pgzrun, et tu ajoutes des effets sonores avec pygame.mixer.
vel_yvel_y négatifpygame.Rectpygame.mixermain.py dans Thonny.Dans un platformer, le personnage tombe en continu vers le bas, sauf s’il se trouve sur une plateforme. On simule ça avec vel_y : une vitesse verticale qui augmente à chaque frame à cause de la gravité.
Cherche le commentaire # STAP 1 dans main.py et remplace le pass par :
# Appliquer la gravité
vel_y += GRAVITY
player_rect.y += vel_y
# Vérifie si le personnage est sur une plateforme
on_ground = False
for platform in platforms:
if (player_rect.colliderect(platform) and vel_y > 0):
player_rect.bottom = platform.top
vel_y = 0
on_ground = TrueGRAVITY = 0.5 est déjà en haut du fichier. Clique sur Run. Le personnage tombe maintenant sur la plateforme la plus proche et y reste.
Que se passe-t-il ici ? À chaque frame, vel_y augmente un peu (le personnage accélère vers le bas). Si le personnage touche une plateforme en tombant (vel_y > 0), tu places son bas (bottom) pile sur le haut de la plateforme et tu arrêtes la chute (vel_y = 0).
Un platformer sans saut, c’est à moitié fini. Appuie sur ESPACE pour sauter : ce n’est rien d’autre que rendre vel_y soudainement négatif.
Cherche le commentaire # STAP 2 et ajoute :
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_rect.x -= SPEED
if keys[pygame.K_RIGHT]:
player_rect.x += SPEED
# Sauter — seulement si tu es au sol
if keys[pygame.K_SPACE] and on_ground:
vel_y = -12Clique sur Run et teste :
Astuce : si le saut te semble trop haut ou trop bas, remplace -12 par -10 (saut plus bas) ou -15 (saut plus haut).
Ajoutons quelque chose à ramasser. Le starter a déjà une liste stars avec des objets pygame.Rect. C’est toi qui écris la détection de collision.
Cherche le commentaire # STAP 3 :
for star in stars[:]: # [:] pour pouvoir supprimer sans risque pendant la boucle
if player_rect.colliderect(star):
stars.remove(star)
score += 1Et dans la fonction de dessin (cherche # TEKEN STERREN) :
for star in stars:
pygame.draw.polygon(screen, YELLOW, star_points(star.centerx, star.centery, 12, 5))star_points() est déjà défini dans le starter. Il calcule les points d’une étoile à 5 branches.
En haut du jeu, il y a score = 0. Dessine le score à l’écran (cherche # TEKEN SCORE) :
score_surf = font.render(f"Étoiles : {score}", True, WHITE)
screen.blit(score_surf, (10, 10))Maintenant, tu ajoutes un son de saut et un écran de victoire quand toutes les étoiles sont ramassées.
Charger le son (c’est déjà prêt dans le starter ; vérifie que jump.wav se trouve dans le dossier sounds/) :
pygame.mixer.init()
jump_snd = pygame.mixer.Sound("sounds/jump.wav")Jouer le son au saut : ajoute ceci au code du saut :
if keys[pygame.K_SPACE] and on_ground:
vel_y = -12
jump_snd.play()Écran de victoire : ajoute ceci après la boucle des étoiles :
if len(stars) == 0:
win_surf = font.render("Gagné ! Toutes les étoiles ramassées !", True, YELLOW)
screen.blit(win_surf, (WIDTH // 2 - win_surf.get_width() // 2, HEIGHT // 2))
pygame.display.flip()
pygame.time.wait(3000)
running = FalseMontre ton jeu à un coach et à un buddy. Tu arrives à ramasser toutes les étoiles avant la fin du temps ?
Le snapshot Dojo Defender d’aujourd’hui continue sur la session 5 :
Télécharge le starter Dojo Defender ou la solution.
« La prochaine fois : clique sur les bugs et ZAPPE-les, avec tes propres classes. »
Essaie une de ces extensions à la maison :
Les bugs tombent du haut vers le bas. Toi, tu tires vers le haut pour les toucher. Dans cette session, tu apprends la POO : tu écris ta première classe à toi (Bug), puis deux sous-classes : une qui oscille et une qui plonge sur toi. Les classes sont les briques de presque tous les gros programmes.
__init__ et tes propres méthodesmain.py dans Thonny.La classe Bug
Cherche le commentaire # ÉTAPE 1 — CLASSE BUG et écris :
class Bug:
def __init__(self, x, y):
self.x = x
self.y = y
self.alive = True
def update(self):
self.y += 2 # tombe vers le bas
def draw(self, screen):
pygame.draw.circle(screen, GREEN, (int(self.x), int(self.y)), 15)
# Yeux
pygame.draw.circle(screen, BLACK, (int(self.x) - 5, int(self.y) - 4), 3)
pygame.draw.circle(screen, BLACK, (int(self.x) + 5, int(self.y) - 4), 3)Faire apparaître des bugs : le starter a déjà un timer. Cherche # SPAWN BUG :
bugs.append(Bug(random.randint(30, WIDTH - 30), -20))Tirer : cherche # TIR (c’est dans la boucle des événements, à K_SPACE) :
bullets.append(pygame.Rect(player_x - 3, player_y - 20, 6, 12))Mets les projectiles à jour à chaque frame (cherche # MISE À JOUR PROJECTILES) :
for b in bullets[:]:
b.y -= 10
if b.y < 0:
bullets.remove(b)
pygame.draw.rect(screen, YELLOW, b) # ceci est déjà en placeMaintenant tu écris la détection de collision : quand un projectile touche un bug, le bug meurt.
Cherche # ÉTAPE 2 — COLLISION :
for bug in bugs[:]:
bug.update()
bug.draw(screen)
if bug.y > HEIGHT + 20:
bugs.remove(bug)
continue
bug_rect = pygame.Rect(bug.x - 15, bug.y - 15, 30, 30)
for bullet in bullets[:]:
if bullet.colliderect(bug_rect):
bug.alive = False
bullets.remove(bullet)
score += 1
break
if not bug.alive:
bugs.remove(bug)Clique sur Run. Tire sur les bugs : ils disparaissent dès que tu les touches !
Maintenant, tu crées une sous-classe : un Bug qui oscille de gauche à droite.
import math
class SlingerBug(Bug):
def __init__(self, x, y):
super().__init__(x, y)
self.start_x = x
self.timer = 0
def update(self):
self.timer += 0.05
self.x = self.start_x + math.sin(self.timer) * 60
self.y += 1.5 # un peu plus lent, mais plus dur à toucher
def draw(self, screen):
super().draw(screen)
# Cercle orange autour, comme repère visuel
pygame.draw.circle(screen, ORANGE, (int(self.x), int(self.y)), 18, 2)Faire apparaître des SlingerBugs : ajoute ceci dans le code de spawn (par exemple un bug sur trois) :
if random.random() < 0.3:
bugs.append(SlingerBug(random.randint(30, WIDTH - 30), -20))
else:
bugs.append(Bug(random.randint(30, WIDTH - 30), -20))super().__init__(x, y) appelle le __init__ de la classe parente (Bug), donc tu ne dois pas réécrire self.x, self.y et self.alive.
Le DuikBug détecte la position du joueur et plonge droit sur lui.
class DuikBug(Bug):
def __init__(self, x, y, player_x_ref):
super().__init__(x, y)
self.player_x_ref = player_x_ref # fonction qui donne le x actuel du joueur
self.speed_x = 0
self.speed_y = 1
def update(self):
target_x = self.player_x_ref()
dx = target_x - self.x
dist = max(abs(dx), 1)
self.x += dx / dist * 2
self.y += 2.5
def draw(self, screen):
super().draw(screen)
pygame.draw.circle(screen, RED, (int(self.x), int(self.y)), 18, 2)Spawn : utilise un lambda pour passer le x du joueur :
bugs.append(DuikBug(random.randint(30, WIDTH - 30), -20, lambda: player_x))Bonus : dessine une barre de HP. Commence avec lives = 3 et enlève-en une quand un bug atteint le bas de l’écran.
Montre ton jeu à un coach et à un buddy. Combien de bugs arrives-tu à zapper avant de ne plus avoir de vies ?
« La prochaine fois : une route infinie dans le ciel, et tout DÉFILE derrière toi. »
Essaie une de ces extensions à la maison :
lives avec 3 vies ; si un bug atteint le bas, tu en perds une.PantserbBug qui a besoin de 3 tirs avant de mourir (utilise un attribut hp).Dans cette session, tu continues aussi à construire Dojo Defender. Tu ajoutes un boss final qui apparaît toutes les 5 vagues, en 3 phases.
Va voir la session 6 de Dojo Defender pour les instructions.
Le starter et la solution sont prêts.
Ton vaisseau vole dans une route aérienne sans fin. L’arrière-plan défile derrière toi, des obstacles rouges arrivent par la droite, et des étoiles rapportent des points. Plus tu survis longtemps, plus ça va vite !
scroll_xmain.py dans Thonny.Un arrière-plan qui défile donne l’illusion du mouvement. On dessine l’arrière-plan deux fois côte à côte et on décale la position à chaque frame.
Cherche # ÉTAPE 1 et ajoute :
# Décaler l'arrière-plan vers la gauche
scroll_x -= speed
if scroll_x <= -WIDTH:
scroll_x = 0
# Dessiner l'arrière-plan deux fois
screen.blit(bg_image, (int(scroll_x), 0))
screen.blit(bg_image, (int(scroll_x) + WIDTH, 0))scroll_x commence à 0 et diminue à chaque frame. Quand il atteint -WIDTH, on revient à 0 : une boucle sans couture.
Clique sur Run. Le ciel défile maintenant derrière ton vaisseau !
Les obstacles arrivent par la droite et vont vers la gauche. Si tu les touches, tu perds une vie.
Mettre les obstacles à jour (cherche # ÉTAPE 2) :
for obs in obstacles[:]:
obs.x -= speed
if obs.x < -obs.width:
obstacles.remove(obs)
pygame.draw.rect(screen, RED, obs)
# Collision
if ship_rect.colliderect(obs):
obstacles.remove(obs)
lives -= 1
if lives <= 0:
running = FalseDessiner les vies :
for i in range(lives):
pygame.draw.rect(screen, RED, (10 + i * 25, 10, 18, 18))Faire apparaître des obstacles (dans l’événement du timer de spawn) :
h = random.randint(40, 120)
obstacles.append(pygame.Rect(WIDTH, random.randint(50, HEIGHT - h - 50), 30, h))Les étoiles rapportent des points et disparaissent quand tu les touches.
Cherche # ÉTAPE 3 :
for star in stars[:]:
star.x -= speed
if star.x < -20:
stars.remove(star)
continue
pygame.draw.circle(screen, YELLOW, star.center, 10)
if ship_rect.colliderect(star):
stars.remove(star)
score += 1
# Dessiner le score :
score_surf = font.render(f"Score : {score}", True, WHITE)
screen.blit(score_surf, (WIDTH - 120, 10))Faire apparaître des étoiles (dans le même timer de spawn, mais moins souvent) :
if random.random() < 0.4:
stars.append(pygame.Rect(WIDTH, random.randint(40, HEIGHT - 40), 20, 20))Maintenant tu rends le jeu de plus en plus difficile à mesure que le score monte.
Faire augmenter la vitesse (cherche # ÉTAPE 4) :
speed = BASE_SPEED + score * 0.1BASE_SPEED = 4 est déjà en haut du fichier. À un score de 20, tout va deux fois plus vite !
Adapter l’intervalle de spawn : plus le score est haut, plus les nouveaux obstacles arrivent souvent :
spawn_interval = max(500, 1800 - score * 30) # min. 500ms
pygame.time.set_timer(SPAWN_EVENT, spawn_interval)Écran de game over :
if not running:
go_surf = font.render("GAME OVER", True, RED)
screen.blit(go_surf, (WIDTH // 2 - go_surf.get_width() // 2, HEIGHT // 2 - 30))
sc_surf = font.render(f"Score : {score}", True, WHITE)
screen.blit(sc_surf, (WIDTH // 2 - sc_surf.get_width() // 2, HEIGHT // 2 + 10))
pygame.display.flip()
pygame.time.wait(3000)Montre ton jeu à un coach et à un buddy. Qui fait le meilleur score ?
« La prochaine fois : un boss qui se défend, en TROIS phases. »
Essaie une de ces extensions à la maison :
Bloqué ? Demande au dojo suivant à un coach, ou essaie simplement autre chose. Programmer, c’est faire.
Aujourd’hui, tu continues aussi à travailler sur Dojo Defender — mais sans instructions pas à pas. C’est toi qui choisis ce que tu construis.
Télécharge le starter Dojo Defender — c’est le jeu complet avec tout dedans (vaisseau, ennemis, astéroïdes, vagues, boss). Choisis une feature dans la liste, planifie-la rapidement avec un coach, et lance-toi.
👉 Tout sur Dojo Defender se trouve sur la page Dojo Defender.
Le boss final t’attend. Il va et vient, tire des projectiles et devient de plus en plus dangereux à mesure que ses HP baissent. Toi, tu tires en retour, tu suis ses HP sur une barre, et tu survis à trois phases. C’est la session la plus difficile, et la plus satisfaisante si tu y arrives.
main.py dans Thonny.Le boss va et vient sur l’écran. Quand il touche le bord, il repart dans l’autre sens.
Cherche # ÉTAPE 1 et ajoute :
boss_rect.x += boss_speed
# Repartir dans l'autre sens au bord
if boss_rect.right >= WIDTH or boss_rect.left <= 0:
boss_speed = -boss_speedboss_speed = 3 est déjà en haut du fichier. Clique sur Run : le boss traverse l’écran de gauche à droite !
Bouger le joueur et tirer (cherche # JOUEUR) :
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and player_rect.left > 0:
player_rect.x -= PLAYER_SPEED
if keys[pygame.K_RIGHT] and player_rect.right < WIDTH:
player_rect.x += PLAYER_SPEED
# Tirer (cherche # TIR dans la boucle des événements) :
player_bullets.append(pygame.Rect(player_rect.centerx - 3, player_rect.top - 15, 6, 15))Collision entre le projectile du joueur et le boss :
Cherche # ÉTAPE 2 :
for b in player_bullets[:]:
b.y -= 8
if b.y < 0:
player_bullets.remove(b)
continue
pygame.draw.rect(screen, YELLOW, b)
if b.colliderect(boss_rect):
player_bullets.remove(b)
boss_hp -= 1
if boss_hp <= 0:
running = False # le joueur gagne !Dessiner la barre de HP (cherche # BARRE HP) :
# Fond de la barre
pygame.draw.rect(screen, DARK_RED, (10, 10, 300, 20))
# Partie remplie selon les HP actuels
breedte = int(300 * boss_hp / BOSS_MAX_HP)
pygame.draw.rect(screen, RED, (10, 10, breedte, 20))
# Texte
hp_surf = font.render(f"HP du boss : {boss_hp}", True, WHITE)
screen.blit(hp_surf, (320, 10))Clique sur Run. Tire sur le boss : la barre de HP diminue !
Le boss tire un projectile vers le bas toutes les N frames.
Cherche # ÉTAPE 3 :
boss_shoot_timer += 1
if boss_shoot_timer >= boss_shoot_interval:
boss_shoot_timer = 0
boss_bullets.append(pygame.Rect(boss_rect.centerx - 4, boss_rect.bottom, 8, 16))Mettre à jour les projectiles du boss :
for b in boss_bullets[:]:
b.y += 6
if b.y > HEIGHT:
boss_bullets.remove(b)
continue
pygame.draw.rect(screen, ORANGE, b)
if b.colliderect(player_rect):
boss_bullets.remove(b)
player_lives -= 1
if player_lives <= 0:
running = FalseDessine player_lives en petits cœurs ou en blocs rouges en bas de l’écran.
Maintenant, le boss réagit à ses HP :
Cherche # ÉTAPE 4 :
if boss_hp > 50:
boss_phase = 1
boss_speed_abs = 3
boss_shoot_interval = 60
elif boss_hp > 25:
boss_phase = 2
boss_speed_abs = 5
boss_shoot_interval = 35
else:
boss_phase = 3
boss_speed_abs = 7
boss_shoot_interval = 20
# Adapter la vitesse sans changer la direction :
boss_speed = boss_speed_abs * (1 if boss_speed > 0 else -1)Phase 3 : projectiles doubles (ajoute ceci dans le code de tir) :
if boss_phase == 3:
boss_bullets.append(pygame.Rect(boss_rect.left + 10, boss_rect.bottom, 8, 16))
boss_bullets.append(pygame.Rect(boss_rect.right - 18, boss_rect.bottom, 8, 16))
else:
boss_bullets.append(pygame.Rect(boss_rect.centerx - 4, boss_rect.bottom, 8, 16))Écran de victoire quand boss_hp <= 0 :
screen.fill(BLACK)
win = font.render("BOSS VAINCU !", True, YELLOW)
screen.blit(win, (WIDTH // 2 - win.get_width() // 2, HEIGHT // 2))
pygame.display.flip()
pygame.time.wait(3000)Montre ton jeu à un coach et à un buddy. Qui atteint la phase 3 et survit ?
« La prochaine fois : ton propre jeu, de zéro, entièrement ton idée. »
Essaie une de ces extensions à la maison :
Cette session est la tienne. Pas d’étapes fixes, pas de mécaniques obligatoires. C’est toi qui décides ce que tu construis, et aujourd’hui tu le fais.
En neuf sessions, tu as appris :
Toutes ces briques sont prêtes. Aujourd’hui, tu les combines dans ton propre jeu.
Pas encore d’idée ? Voilà quelques genres pour commencer :
Dodge game : esquive des objets qui arrivent de plus en plus vite. Simple mais accrocheur.
Platformer : saute de plateforme en plateforme, ramasse des items, évite les ennemis.
Shooter : descends les ennemis qui arrivent d’en haut ou sur le côté.
Jeu de puzzle : fais glisser des blocs, relie des points, ou résous un motif.
Jeu de course : dessine un parcours et fonce vers l’arrivée le plus vite possible.
Raconte une histoire : pas de score, pas de vies. Laisse le joueur cliquer et faire des choix.
Tu peux aussi combiner : un shooter avec des éléments de puzzle, un platformer avec un boss à la fin. Tout est permis.
Avant d’écrire du code, réponds à ces trois questions :
Écris tes réponses sur une feuille ou dans un commentaire en haut de ton code. Ça t’aide à rester concentré quand tu bloques.
Tu veux une animation en boucle, une explosion ou un objet qui clignote ? Fais une liste de noms d’images et change actor.image toutes les N millisecondes. La démo ci-dessous montre comment ça marche : utilise le curseur pour changer la vitesse et le bouton pour mettre en pause :
En Python, tu utilises alors une liste de noms d’images et un timer :
frames = ['lopen_1', 'lopen_2', 'lopen_3', 'lopen_4']
anim_timer = 0
FRAME_DUUR = 10 # frames (à 60 fps = ~167 ms)
def update():
global anim_timer
anim_timer += 1
speler.image = frames[(anim_timer // FRAME_DUUR) % len(frames)]Télécharge le starter via ce lien. Le starter a :
draw() et update() videOuvre main.py et commence par l’étape 1 de ton propre plan. Le cheatsheet de cette page a tous les patrons des sessions précédentes sous la main.
Bloqué ? Demande à un coach. Décris ce que tu veux obtenir, pas seulement ce qui ne marche pas. Comme ça, on peut chercher ensemble la meilleure approche.
Fini trop vite ? Ajoute du son, fais un écran de démarrage, ou ajoute un deuxième joueur.
À la fin de la session, chacun présente son jeu. Tu ne dois pas l’avoir terminé. Montre ce que tu as fait et raconte :
CoderDojo s’arrête après dix sessions. Construire toi-même, ça ne s’arrête pas.
Continue à construire. Les petits projets t’apprennent plus que les gros cours. Fais un jeu pour ton frère ou ta sœur, pour ton animal, ou juste pour toi.
Besoin d’inspiration ?
CoderDojo revient. Toi aussi ?
Cinq sessions sur Git et GitHub, de ton premier commit aux pull requests. Plus une session bonus sur Markdown, le langage dans lequel tu écris tes notes et ta documentation.
.gitignore et des astuces de workflow.Imagine : tu travailles trois heures sur ton jeu. Tu ajoutes une arme trop cool. Mais… maintenant le reste de ton jeu ne marche plus. Et tu ne sais plus ce que tu as changé exactement. Trois heures de travail perdues.
Git est la solution. Git se souvient de chaque version de tes fichiers. Comme un bouton « annuler » infini qui n’oublie jamais ce que tu as fait.
Dans cette session, tu installes Git, tu crées ton premier dépôt et tu enregistres pour toujours ce que tu fais : étape par étape, version par version. Et le plus chouette : Git ne sert pas qu’au code. Il marche aussi pour tes notes, tes travaux d’école et tes histoires.
Git est un système de gestion de versions. Il garde une trace de ce que tu changes dans tes fichiers, quand tu l’as fait, et pourquoi. Chaque fois que tu as fini un morceau de travail, tu fais un commit : une photo de tous tes fichiers à ce moment-là.
Ce qui rend Git spécial :
Git a été créé par Linus Torvalds, la même personne qui a construit Linux. Il avait besoin d’un outil pour travailler sur le noyau Linux avec des milliers de programmeurs en même temps. En 2005, il a construit Git en un week-end. Aujourd’hui, presque tous les développeurs du monde l’utilisent.
Git a été conçu pour le code source, mais il fonctionne avec tous les fichiers texte. Un fichier texte, c’est n’importe quel fichier que tu peux ouvrir et lire avec le Bloc-notes ou un éditeur simple : .py, .html, .css, .json, .txt, .csv, .md (Markdown), .yml, .toml, tout ce que tu veux.
Ce que Git ne sait pas bien faire : les fichiers binaires. Ce sont des fichiers qui ne sont pas du texte lisible : des images (.png, .jpg), des vidéos (.mp4), des programmes compilés (.exe), des documents Word (.docx). Git peut les suivre, mais c’est plus lent et tu ne vois pas ce qui a changé exactement. Avec un fichier texte, git diff montre chaque lettre que tu as ajoutée ou enlevée. Avec un .png, Git dit seulement « ce fichier a changé », mais pas ce qui a changé dans l’image.
Beaucoup d’applications de notes d’aujourd’hui utilisent Markdown (des fichiers .md) pour stocker tes documents. Par exemple :
.md dans un dossier de ton ordinateurComme les fichiers Markdown sont de simples fichiers texte, tu peux les mettre sous Git. Tu gardes l’historique de tes notes, tu peux revenir à une version précédente d’un document, et tu peux partager tes notes via GitHub, exactement comme tu le fais avec du code.
Mettre un dossier de notes Markdown sous Git est aussi simple qu’un projet Python :
mkdir mijn-notities
cd mijn-notities
git init
echo "# Mes notes" > start.md
git add start.md
git commit -m "Première note : page de départ"À partir de ce moment, Git garde chaque modification de tes notes. Tu écris un travail pour l’école en Markdown ? Commit chaque paragraphe. Tu travailles à la construction d’un monde pour une histoire ? Git retient chaque version de ton intrigue.
| Utilise Git | Mieux avec autre chose |
|---|---|
Notes en Markdown (.md) | Notes en Word (.docx) |
Fichiers de configuration (.json, .yml) | Grandes images ou vidéos avec tes notes |
| Textes : travaux, histoires, blogs | Collaboration en temps réel comme Google Docs (Git est trop lent pour ça) |
| Tes cheatsheets CoderDojo | Mots de passe ou journaux intimes (sauf dépôt privé) |
En résumé : tout ce qui est du texte peut aller dans Git. Tout ce qui est binaire, mieux vaut éviter.
Sans Git, ton workflow ressemble à ça :
game.py
game_backup.py
game_backup2.py
game_final.py
game_final_echt.py
game_final_echt_nieuwe_wapens.pyTu reconnais ? Avec Git, tu n’as besoin que d’un seul fichier : game.py. Git se souvient du reste.
Ce que la gestion de versions t’apporte :
Git est fait pour les fichiers texte : les fichiers que tu écris toi-même : code, notes, configuration. Il y a des choses que tu gardes mieux en dehors de Git :
| Mets dans Git | Ne mets PAS dans Git |
|---|---|
Tes fichiers Python (.py) | Mots de passe, clés API, tokens |
| Les images utilisées par ton jeu | Les fichiers que ton programme crée lui-même (.exe, .pyc) |
Les fichiers son (.wav, .mp3) | Le dossier __pycache__ |
| Les fichiers texte, la configuration | Les gros fichiers (>50 MB) comme les vidéos |
Ton README.md | Les réglages de ton ordinateur à toi |
Pourquoi pas de mots de passe dans Git ? Parce que Git se souvient de tout, pour toujours. Même si tu supprimes un mot de passe plus tard, il est encore dans l’historique. Quiconque voit ton code un jour peut remonter jusqu’à ce commit. Et si ton code arrive un jour sur GitHub, ton mot de passe est sur internet. Pour l’éternité.
Utilise un fichier .gitignore pour dire à Git quels fichiers il doit ignorer. Tu vas voir ça tout de suite.
Ouvre le Terminal (cherche « Terminal » dans Spotlight) et tape :
git --versionSi Git n’est pas installé, macOS te demande d’installer les developer tools. Clique sur « Install ». C’est fait.
sudo apt install gitOuvre un terminal (Git Bash sous Windows) et tape :
git --versionTu vois quelque chose comme git version 2.47.0. Ça veut dire : Git est prêt.
Git veut savoir qui tu es, pour pouvoir mettre ton nom sur chaque commit. Tu fais ça une seule fois, ensuite Git s’en souvient.
git config --global user.name "Ton Nom"
git config --global user.email "ton@email.com"Utilise la même adresse e-mail que celle que tu utiliseras tout à l’heure pour GitHub. Ça rend le couplage plus simple.
Astuce : --global veut dire : ce réglage vaut pour tous tes projets Git. Tu ne dois le faire qu’une seule fois.
Un dépôt (ou « repo ») est un dossier où Git garde les versions. On en crée un.
Crée d’abord un nouveau dossier pour ton projet :
mkdir mijn-eerste-git-project
cd mijn-eerste-git-projectMaintenant tu dis à Git : « Ce dossier est un dépôt. »
git initTu vois : Initialized empty Git repository in .../mijn-eerste-git-project/.git/
Git a créé un dossier caché .git. C’est là qu’il garde tout : l’historique, les commits, la configuration. Ne touche jamais ce dossier à la main, c’est Git qui le gère.
Crée un fichier. Par exemple un fichier Python avec une seule ligne :
echo 'print("Salut Git !")' > hallo.pyMaintenant tu dis à Git : « Fais attention à ce fichier. »
git add hallo.pyAvec git add, tu mets des fichiers dans la staging area : une zone intermédiaire. Tu dis à Git : « Ces changements, je veux les mettre dans mon prochain commit. »
Vérifie ce qui est prêt :
git statusGit affiche :
On branch master
Changes to be committed:
new file: hallo.pyMaintenant vient le commit lui-même :
git commit -m "Mon premier commit : hallo.py ajouté"Que se passe-t-il ici ? -m veut dire « message ». Le texte entre guillemets est ton commit message : une courte explication de ce que tu as changé. Git a maintenant pris une photo permanente de ton projet.
Des bons commit messages : écris en anglais (c’est la convention dans presque tous les projets). Commence par un verbe : « Add », « Fix », « Update ». Reste court : 72 caractères maximum.
Ouvre hallo.py dans un éditeur de texte. Change la ligne par :
print("Salut Git ! Tu te souviens de mon code.")Enregistre le fichier. Regarde maintenant ce que Git voit :
git statusGit sait que hallo.py a changé. Mais qu’est-ce qui a changé exactement ?
git diffgit diff montre exactement quelles lignes tu as ajoutées (en vert avec +) et supprimées (en rouge avec -). C’est une des choses les plus puissantes de Git : tu vois littéralement ce qui a changé, caractère par caractère, depuis ton dernier commit.
Committe la modification :
git add hallo.py
git commit -m "Update : salutation étendue"C’est ici que Git devient magique. Imagine : tu regrettes ta dernière modification. Tu veux revenir à la première version.
Montre d’abord tous les commits :
git log --onelineTu vois quelque chose comme :
a1b2c3d Update : salutation étendue
e4f5g6h Mon premier commit : hallo.py ajoutéChaque commit a un code unique, un hash. Ce long code (raccourci à 7 caractères) identifie exactement cette version-là de ton projet.
Pour voir à quoi ressemblait hallo.py dans le premier commit :
git show e4f5g6h:hallo.pyVoilà ton print("Salut Git !") d’origine.
Tu veux vraiment retourner dans le temps ? C’est possible :
git checkout e4f5g6h -- hallo.pyMaintenant hallo.py est de nouveau comme dans ton premier commit. Vérifie avec cat hallo.py. Tu vois l’ancienne version. Mais ne t’inquiète pas : ton deuxième commit n’a pas disparu. Avec git checkout master -- hallo.py, tu reviens à la dernière version.
.gitignoreCrée un fichier que Git doit ignorer :
echo "GEHEIM_WACHTWOORD=12345" > geheimen.txtgit status montre maintenant ce fichier comme « untracked ». Git l’a vu, mais il ne sait pas si tu veux le suivre. Tu peux l’ignorer avec un fichier .gitignore :
echo "geheimen.txt" > .gitignoreMaintenant git status à nouveau et geheimen.txt a disparu de la liste. Git l’ignore. (Ajoute bien .gitignore lui-même à Git avec git add .gitignore et git commit, pour que les autres sachent aussi ce qu’il faut ignorer.)
Un bon .gitignore pour un projet Python :
# Python
__pycache__/
*.pyc
*.pyo
# Secrets
*.env
secrets.txt
# Ton éditeur
.vscode/
.idea/Montre à un coach et à un buddy :
git log --oneline : ton historique de commits.git diff qui montre ce que tu as changé..gitignore.« La prochaine fois : deux versions de ton code en même temps. Tu travailles sur une nouvelle feature pendant que l’ancienne version continue de marcher. Ça s’appelle des branches, et c’est ce qui rend Git vraiment puissant. »
git diff pour regarder la modification, et committe-la avec un bon message.git show pour regarder chaque version. Utilise git checkout pour revenir au premier commit, puis de nouveau au dernier..gitignore. Fais en sorte que __pycache__/ et les fichiers .pyc soient vraiment ignorés (vérifie avec git status).Bloqué ? Demande au dojo suivant à un coach, ou essaie simplement autre chose. Programmer, c’est faire. Apprendre Git, c’est faire.
La session précédente, tu as appris à faire des commits : des photos de ton code sur une seule ligne du temps. Tout bien à la suite.
Mais si tu veux essayer une nouvelle idée ? Ajouter un pistolet laser à ton jeu, par exemple. Tu ne sais pas si ça va marcher. Tu ne veux pas casser ton code qui fonctionne.
C’est pour ça que les branches existent.
Une branche est une copie de ton code où tu peux expérimenter librement. Ton code principal (la branche master) reste en sécurité. Si ton expérience marche, tu la recolles dans master. Si elle ne marche pas ? Tu jettes la branche. Ta branche master n’en a jamais rien su.
Note : sur GitHub et dans beaucoup de nouveaux projets, la branche principale s’appelle
mainau lieu demaster. C’est exactement la même chose, seul le nom change. Dans ce cours, on utilisemaster, mais si tu croisesmainen ligne, tu sais que ça veut dire la même chose.
Ouvre ton terminal dans le projet de la session précédente. Vérifie où tu es :
git status
git log --onelineTu as quelques commits sur master. C’est ta base stable : c’est d’ici que tu vas te séparer tout à l’heure.
Tu vas ajouter une nouvelle feature : un fichier highscore.txt qui garde le meilleur score. Mais d’abord, tu crées une branche :
git branch highscore-featureGit a maintenant créé une nouvelle branche. Mais tu es toujours sur master. Vérifie quelles branches existent :
git branchTu vois :
highscore-feature
* masterL’astérisque à côté de master veut dire : « tu es ici ». Passe à ta nouvelle branche :
git switch highscore-feature(Les versions plus anciennes de Git utilisent git checkout highscore-feature. Les deux marchent.)
Encore une fois git branch : l’astérisque est maintenant à côté de highscore-feature. Tout ce que tu commites maintenant se passe sur cette branche. master reste intact.
Astuce : tu peux créer une branche et y aller directement en une seule commande :
git switch -c mijn-nieuwe-branch-c veut dire « create ». C’est plus rapide et tu n’oublies jamais de changer de branche.
Crée un nouveau fichier :
echo "HIGHSCORE: 0" > highscore.txtCommitte ton travail :
git add highscore.txt
git commit -m "Add highscore.txt avec valeur de départ 0"Ajoute encore un fichier qui lit le highscore :
echo 'def lees_highscore():' > highscore_manager.py
echo ' with open("highscore.txt") as f:' >> highscore_manager.py
echo ' return int(f.read().split(": ")[1])' >> highscore_manager.pyCommitte encore :
git add highscore_manager.py
git commit -m "Add highscore_manager : fonction pour lire le highscore"Regarde maintenant ton log :
git log --onelineTu vois tous tes commits de master, plus les deux nouveaux. Git se souvient de toute la chaîne.
Reviens sur master :
git switch masterRegarde ce qu’il y a ici :
lshighscore.txt et highscore_manager.py ont… disparu. Ils existent seulement sur la branche highscore-feature. Sur master, tout est encore exactement comme tu l’as laissé.
C’est la magie des branches : deux (ou plus) versions de ton projet, en même temps sur ton ordinateur, sans se gêner.
Change encore une fois dans les deux sens pour le sentir :
git switch highscore-feature # les fichiers sont revenus
git switch master # les fichiers ont encore disparugit mergeTa feature highscore fonctionne. Il est temps de la remettre dans master. Ça s’appelle merger.
Assure-toi d’être sur master :
git switch masterFusionne la branche :
git merge highscore-featureGit affiche quelque chose comme Updating a1b2c3d..e4f5g6h et Fast-forward. Tes commits de highscore-feature font maintenant partie de master. Vérifie :
ls
git log --onelinehighscore.txt et highscore_manager.py sont maintenant sur master. Tous les commits de la branche feature sont repris dans l’historique.
Imagine : tu as changé quelque chose sur master dans highscore.txt, par exemple “HIGHSCORE: 100” au lieu de “HIGHSCORE: 0”. Et en même temps, sur une autre branche, tu as aussi changé highscore.txt, en “HIGHSCORE: 500”.
Si tu essaies de merger maintenant, Git ne sait pas quelle version est la bonne. C’est un merge conflict. Git te demande à toi de décider.
Provoquons-le exprès.
Sur master :
echo "HIGHSCORE: 100" > highscore.txt
git add highscore.txt
git commit -m "Update highscore à 100 sur master"Crée une nouvelle branche et change le même fichier :
git switch -c andere-highscore
echo "HIGHSCORE: 500" > highscore.txt
git add highscore.txt
git commit -m "Update highscore à 500"Reviens sur master et essaie de merger :
git switch master
git merge andere-highscoreGit dit : CONFLICT (content): Merge conflict in highscore.txt. Ouvre highscore.txt dans ton éditeur. Tu vois :
<<<<<<< HEAD
HIGHSCORE: 100
=======
HIGHSCORE: 500
>>>>>>> andere-highscoreCe sont les deux versions. HEAD, c’est ta version master. En dessous se trouve la version de andere-highscore. Tu choisis laquelle tu gardes, ou tu les combines.
Supprime les marqueurs et choisis une version :
HIGHSCORE: 500Enregistre le fichier. Dis à Git que le conflit est résolu :
git add highscore.txt
git commit -m "Merge : highscore de andere-highscore choisi"Conflit résolu. Git peut continuer.
Ta feature est mergée. Tu n’as plus besoin de la branche :
git branch -d highscore-feature
git branch -d andere-highscore-d veut dire « delete ». Git refuse de supprimer une branche qui n’est pas encore mergée : c’est une soupape de sécurité. Si tu veux vraiment jeter une branche sans la merger, utilise -D (majuscule). Mais fais attention avec ça.
| Une branche, oui | Pas de branche |
|---|---|
| Une nouvelle feature qui prend du temps | Corriger une faute dans un commentaire |
| Une expérience dont tu ne sais pas si ça marche | Un petit bugfix d’une ligne |
| Quelque chose qui peut casser ton code qui marche | Tu travailles seul et ta modification est claire |
| Tu travailles avec d’autres | (en solo, master suffit souvent) |
Règle de base : si tu hésites, fais une branche. Une branche ne coûte rien. Perdre du code, si.
master change entre-temps, et plus le risque de conflicts augmente.master. Des merges petits et fréquents sont plus faciles qu’un seul gros merge monstre.highscore-feature, c’est bien. test123 ou branch2, c’est mauvais. Dans une semaine, tu ne sauras plus ce qu’il y avait dans test123.git branch ou git status te dit sur quelle branche tu es. Fais-en une habitude, pour éviter d’écrire par accident du code sur master qui appartient en fait à une branche feature.Montre à un coach et à un buddy :
git branch avec au moins deux branches (dont master).master.« Jusqu’ici, tout ton code vit seulement sur ton laptop. La prochaine fois, on le met en ligne. Tu crées un compte GitHub, tu pushes ton dépôt sur internet, et ton jeu est visible partout dans le monde. Et : tu peux collaborer avec d’autres. GitHub : ton code dans le monde entier. »
master. Vérifie après chaque merge que tout marche encore.master, fais là aussi une modification dans le même fichier, et merge la branche. Résous le conflit soigneusement et vérifie avec git log --graph à quoi ressemble l’historique.Jusqu’ici, tout ton code vit sur ton laptop. Pratique pour toi, mais personne d’autre n’y a accès. Et si ton laptop plante, tu perds tout.
GitHub est un site web où tu mets tes dépôts Git en ligne. C’est une sauvegarde, un portfolio et une plateforme de collaboration en un seul. Aujourd’hui, tu mets ton code sur GitHub. À la fin de cette session, n’importe qui avec une connexion internet peut voir tes projets, et toi ceux des autres.
GitHub, ce n’est pas la même chose que Git. Git est le système de gestion de versions qui tourne sur ton ordinateur. GitHub est un site web (github.com) qui héberge des dépôts Git : une sorte de Google Drive pour le code, mais avec Git en dessous.
Ce que GitHub ajoute à Git :
GitHub n’est pas la seule option ; il y a des alternatives comme GitLab et Bitbucket. Mais GitHub est le plus grand, avec plus de 100 millions d’utilisateurs. Dans ces sessions, on utilise GitHub.
git config à la session 11 : ça évite des soucis.Astuce pour les coaches : vérifie que les ninjas ont accès à leur e-mail pendant la session. Certains laptops ne sont pas connectés au webmail. Prépare un plan B : si la vérification par e-mail ne marche pas, les ninjas peuvent vérifier leur compte GitHub plus tard à la maison. Le reste de la session marche aussi sans vérification.
Tu as un projet local sur ton ordinateur (de la session 11). Tu vas le mettre en ligne.
Sur GitHub, clique en haut à droite sur l’icône + → New repository.
Remplis :
| Champ | Ce que tu remplis |
|---|---|
| Repository name | mijn-eerste-git-project (le même que ton dossier local) |
| Description | “Mon premier projet Git (CoderDojo session 11)” |
| Public / Private | Choisis Public : les autres peuvent voir ton code |
| Initialize with README | NE coche PAS : tu as déjà un projet local |
Clique sur Create repository.
GitHub affiche maintenant des instructions. Choisis le bloc sous "…or push an existing repository from the command line". Copie ces trois commandes : tu en auras besoin tout de suite.
Dans ton terminal (dans ton dossier de projet) :
git remote add origin https://github.com/JOUW_USERNAME/mijn-eerste-git-project.gitQue se passe-t-il ici ? remote est un endroit externe où ton repo se trouve aussi. origin est le nom que tu donnes à cet endroit. « origin » est le nom par défaut de ta remote principale. Tu peux avoir plusieurs remotes (par exemple origin pour GitHub, backup pour GitLab), mais une seule suffit la plupart du temps.
Vérifie que ça a marché :
git remote -vTu vois :
origin https://github.com/JOUW_USERNAME/mijn-eerste-git-project.git (fetch)
origin https://github.com/JOUW_USERNAME/mijn-eerste-git-project.git (push)fetch = c’est de là que tu récupères du code. push = c’est là que tu envoies ton code. La plupart du temps, c’est le même endroit.
git pushVoilà le moment : envoyer tes commits locaux vers GitHub.
git push -u origin masterpush = envoie mes commits vers la remote. -u origin master = « retiens que master sur mon ordinateur correspond à master sur origin. » La prochaine fois, tu peux juste taper git push, parce que Git se souvient du lien.
GitHub demande de te connecter. Deux possibilités :
repo, copie le token, et colle-le comme mot de passe dans le terminal.Pour les ninjas : la méthode 1 (navigateur) est la plus simple. Si ça ne marche pas, aide-les avec un token.
Après un push réussi, rafraîchis ta page GitHub. Tes fichiers sont là ! Ton hallo.py, ton historique de commits : tout.
Fais une modification en local :
echo 'print("GitHub is cool!")' >> hallo.py
git add hallo.py
git commit -m "Add GitHub enthusiasm"Pushe vers GitHub :
git pushTu n’as plus besoin de -u origin master, parce que Git connaît le chemin. Rafraîchis GitHub : ton nouveau commit est là.
C’est la route inverse : tu commences sur GitHub et tu le ramènes sur ton ordinateur.
Sur GitHub : New repository. Appelle-le python-spelletje. Cette fois, coche bien Add a README file ; GitHub crée alors un repo avec un fichier dedans. Clique sur Create repository.
Maintenant tu ramènes ce repo sur ton ordinateur. Ça s’appelle cloner :
cd ~ # va dans ton dossier home
git clone https://github.com/JOUW_USERNAME/python-spelletje.gitGitHub crée un dossier python-spelletje avec le README dedans. Et c’est tout de suite un dépôt Git complet : le dossier .git est déjà là. Tu ne dois pas faire de git init.
cd python-spelletje
git log --oneline # tu vois le premier commit que GitHub a fait pour toiMaintenant tu peux continuer à travailler ici en local et pusher tes commits vers GitHub, exactement comme aux étapes 3 à 4.
Imagine : tu as travaillé à python-spelletje à la maison et tu as pushé. Maintenant tu es au dojo avec un laptop et tu veux continuer. Tu n’as pas encore la dernière version.
git pullgit pull récupère les derniers commits de GitHub sur ton ordinateur. C’est deux actions en une : git fetch (récupérer) + git merge (fusionner avec ton code local).
Fais toujours git pull avant de commencer à travailler, sinon tu prends du retard et tu récoltes des merge conflicts.
Résumé du workflow :
| Commande | Ce qu’elle fait |
|---|---|
git pull | Récupérer la dernière version depuis GitHub |
Travailler à ton code, faire des commits (git add, git commit) | |
git push | Envoyer tes commits vers GitHub |
Retiens : pull avant de commencer, push quand tu as fini.
Montre à un coach et à un buddy :
git push tout frais qui vient d’arriver sur GitHub.« Maintenant ton code est en ligne. Mais qu’est-ce que tu mets dans un commit message ? Comment écrire un message qui sera encore clair dans trois mois ? Et comment travailler avec une équipe sans tout casser ? La prochaine fois : le côté professionnel de Git : les best practices que tous les développeurs utilisent. »
git pull.Tu sais taper des commandes Git. Ton code est sur GitHub. Mais il y a une différence entre « utiliser Git » et « bien utiliser Git ».
Cette session parle des habitudes que les développeurs expérimentés appliquent chaque jour. Pas de nouvelles commandes, mais des règles plus précises. À la fin, tu écriras des commit messages qui te serviront encore dans un an, et tu travailleras avec une stratégie de branching qui garde ton projet clair.
git stash et quand l’utiliserUn mauvais commit message ressemble à ça :
git commit -m "fix"
git commit -m "update"
git commit -m "trucs modifiés"Dans trois mois, tu regardes en arrière. C’était quoi « fix » ? Quels « trucs » ? Tu ne le sais plus. Tu dois fouiller dans le code pour retrouver ce qui s’est passé. C’est du temps perdu.
Un commit message professionnel a trois parties :
1. Un résumé court (72 caractères max)
Écris en anglais. Commence par un verbe au présent. Ça s’appelle l’« imperative mood » : comme si tu donnais un ordre à ta base de code. Pense : « Add », « Fix », « Remove », « Update », « Refactor ».
Add highscore tracking
Fix star spawning off-screen
Remove unused collision code2. Une ligne vide
3. Une explication plus longue (optionnel, si c’est utile)
Add highscore tracking
Sauvegarde le meilleur score dans highscore.txt. Le score est
mis à jour après chaque game-over. Le fichier est créé s'il
n'existe pas encore.
Ça remplace l'ancienne méthode où le score restait seulement
en mémoire et se perdait à la fermeture du jeu.L’explication détaillée raconte pourquoi tu as changé quelque chose, pas seulement quoi. Le code lui-même montre déjà le « quoi ». C’est le « pourquoi » dont tu auras besoin dans trois mois.
| À faire | À ne pas faire |
|---|---|
| “Add player health bar” | “added health bar thing” |
| “Fix collision detection on left wall” | “fix” |
| “Remove debug print statements” | “cleanup” |
| 72 caractères max pour le titre | Une histoire entière dans le titre |
| Présent, anglais | Passé (« added », « fixed ») |
Pourquoi l’anglais ? Parce que presque tous les projets open source utilisent l’anglais. Le code est international. Ton code Python aussi, tu l’écris en anglais (def calculate_score). Tes commit messages suivent la même langue.
Pourquoi le présent ? Un commit décrit ce que cette modification fait, pas ce que toi tu as fait. « Add feature » (ce commit ajoute une feature), pas « Added feature » (j’ai ajouté une feature un jour). Git lui-même utilise le présent : Merge branch 'feature', pas Merged.
Tu peux écrire un commit message sur plusieurs lignes en ne fermant pas les guillemets :
git commit -m "Add highscore tracking
Sauvegarde le meilleur score dans highscore.txt. Le fichier est
créé automatiquement au premier game-over."Attention : tu ne tapes le guillemet fermant qu’à la dernière ligne. Tout ce qu’il y a entre les deux fait partie de ton message.
Committe souvent. Committe petit.
Pas : trois heures de travail, un seul commit énorme avec 47 fichiers modifiés. Oui : un commit toutes les 15 à 30 minutes, chaque fois qu’un petit morceau logique est fini.
Règle de base : si ton commit message contient « et », ton commit est trop gros. « Add highscore tracking et fix menu bug et update sprites » → ça doit être trois commits séparés.
Des petits commits facilitent :
Tu sais déjà comment créer des branches (session 12). Maintenant : quand et pourquoi.
master marche toujoursLa branche master, c’est ta vitrine. Quelqu’un qui clone ton repo doit pouvoir lancer ton code sans message d’erreur. master ne contient jamais du travail à moitié fini.
Pas ok sur master : du code avec # TODO: encore à finir, des fonctions en commentaire, des expériences que tu « répareras plus tard ».
Ok sur master : du code qui marche. Point.
Une branche fait exactement une chose. Pas plus.
feature/player-health-barfeature/health-bar-and-menu-and-sound-effectsSi, en travaillant sur une feature, tu penses : « Oh, je peux aussi réparer ce bug de menu vite fait » : stop. Fais une nouvelle branche pour le bugfix. Merge-la d’abord. Ensuite, continue ta feature.
Une branche qui existe depuis plus de quelques jours devient un problème. master change entre-temps, et ta branche prend du retard. Plus tu attends pour merger, plus le risque de merge conflicts augmente.
Merge ta branche dès que la feature est finie. Pour les petites choses (un bugfix de 10 minutes) : tu n’as peut-être même pas besoin d’une branche séparée.
Donne aux branches des noms que tu comprendras encore dans une semaine :
feature/highscore-tracking
bugfix/star-spawn-offscreen
experiment/particle-effectsLe préfixe (feature/, bugfix/, experiment/) dit tout de suite quel genre de travail se trouve dans cette branche. C’est une convention, pas une obligation technique, mais ça aide.
git stash : mettre du travail de côtéImagine : tu travailles sur une branche feature. Ton code est à moitié fini. Tu veux passer vite fait sur master pour un bugfix, mais tu ne veux pas committer ton travail à moitié fini. C’est pour ça que git stash existe :
git stashGit garde toutes tes modifications de côté et remet ton working directory au dernier commit. Tu peux maintenant switcher, faire le bugfix, committer, et revenir :
git switch master
# ... faire le bugfix, committer ...
git switch feature-branch
git stash popgit stash pop ramène tes modifications gardées de côté. Tout est de nouveau comme tu l’as laissé : à moitié fini, mais bien gardé.
git pull --rebase : un historique plus propreNormalement, git pull fait un merge. Ça crée un commit de merge en plus. Parfois tu n’en veux pas ; tu veux une ligne droite de commits sans branches.
git pull --rebaseÇa récupère les derniers commits et met tes commits locaux par-dessus, comme si tu les avais faits après les commits du remote. Le résultat, c’est un historique linéaire : pas de merge-commits qui disent seulement « Merge branch ‘master’ ».
Attention : n’utilise --rebase que sur des branches que tu es seul à utiliser. Sur des branches partagées, un simple git pull (merge) est plus sûr.
Avant de faire git push :
git pullToujours. Même si tu penses que personne d’autre n’a pushé. Ça prend une seconde et ça évite que GitHub refuse ton push avec « Updates were rejected because the remote contains work that you do not have locally. »
Cette règle compte surtout quand tu travailles à plusieurs. Si tu es le seul à travailler sur un repo, le risque est plus petit, mais l’habitude vaut de l’or.
.gitignore qu’il te faut toujoursChaque projet a des fichiers qui n’ont rien à faire dans Git. Ton .gitignore est ta première ligne de défense contre un mot de passe commité par accident.
.gitignore minimal pour un projet Python :
# Python
__pycache__/
*.pyc
*.pyo
# Environnement virtuel
venv/
.venv/
# Variables d'environnement (contiennent souvent des mots de passe/clés)
.env
# Ton éditeur
.vscode/
.idea/
*.swp
*.swo
# Fichiers du système
.DS_Store
Thumbs.dbPourquoi ignorer __pycache__/ ? Ce sont des fichiers Python compilés que ton programme crée automatiquement. Ils sont différents selon la version de Python et selon l’ordinateur. Les mettre dans Git, ça ne fait que du bruit.
Pourquoi ignorer .env ? Les fichiers .env contiennent souvent des clés secrètes, des API keys, des mots de passe de base de données. Ceux-là ne doivent jamais, mais alors jamais, aller dans Git.
Montre à un coach et à un buddy :
.gitignore.« Maintenant tu travailles avec Git comme un pro. Mais il reste un concept que chaque équipe utilise : la pull request. Ton code est prêt, mais avant qu’il arrive dans master, quelqu’un d’autre doit l’approuver. Comment ça marche ? La prochaine fois : les pull requests, le mur de review par lequel chaque modification doit passer. »
feature/, travaille dedans, merge-la et supprime-la. Fais pareil pour une branche bugfix/.git stash pour garder du travail à moitié fini, switch sur master, fais un fix rapide, push, et reviens sur ta feature avec git stash pop.git pull échoue (clone ton repo dans deux dossiers, fais un commit différent dans les deux, push le premier, et essaie de pusher le second). Résous-le : git pull, répare le merge conflict, et seulement après, pushe.Tu as construit une feature sur une branche. De bons commit messages, du travail propre. Maintenant tu veux mettre ton code dans master.
Tu pourrais faire git merge et c’est fini. Mais en équipe, ça ne marche pas. Quelqu’un d’autre doit d’abord regarder ton code : vérifier les erreurs, le style, les choses que tu as oubliées. Voilà ce qu’est une pull request.
Une pull request (PR) est une demande : « Récupère mes modifications. » Tu l’ouvres sur GitHub. Tes coéquipiers regardent ton code, donnent du feedback. Toi, tu modifies des choses. C’est seulement quand tout le monde est content que le code part vers master.
Dans cette session, tu fais ta première pull request. Tu reviewes celle d’un buddy. Et tu découvres ce que ça fait vraiment, le travail d’équipe avec Git.
Aujourd’hui, tu travailles avec un buddy. Décidez qui est l’auteur (celui qui construit la feature) et qui est le reviewer (celui qui regarde la PR). À la moitié, vous échangez.
L’auteur a besoin d’un repo GitHub auquel le reviewer a accès. La façon la plus simple :
Maintenant, vous pouvez tous les deux pusher vers le même repo.
Alternative (sans accès collaborator) : le reviewer forke le repo de l’auteur et ouvre une PR depuis le fork vers l’original. Mais aujourd’hui, on garde ça simple : accès collaborator direct.
L’auteur clone le repo (si ce n’est pas encore fait) et crée une branche feature :
git clone https://github.com/AUTEUR_USERNAME/ons-samenwerk-project.git
cd ons-samenwerk-project
git switch -c feature/groet-functieCrée un nouveau fichier :
echo 'def groet(naam):' > groet.py
echo ' return f"Hallo {naam}!"' >> groet.pyCommitte et pushe :
git add groet.py
git commit -m "Add groet function
Retourne une salutation pour le nom donné."
git push -u origin feature/groet-functiebase: master ← compare: feature/groet-functie.)## Quoi
Une fonction `groet(naam)` qui retourne une salutation.
## Pourquoi
On a besoin d'une salutation réutilisable pour
l'interface utilisateur. Ça évite de devoir écrire
la même string à plusieurs endroits.
## Comment tester
```python
from groet import groet
print(groet("CoderDojo")) # "Hallo CoderDojo!"5. Clique sur **Create pull request**.
Ta PR est maintenant ouverte. Toute personne qui a accès au repo peut la voir. GitHub montre le diff : exactement quelles lignes tu as ajoutées (en vert) et supprimées (en rouge).
## Étape 3 : Reviewer une PR (reviewer)
Le reviewer ouvre la PR sur GitHub. Voici les étapes d'une review :
### 1. Lis la description
Tu comprends ce que fait cette PR ? Si non, demande des explications.
### 2. Regarde le diff
Clique sur l'onglet **Files changed**. GitHub montre chaque ligne modifiée. Regarde :
- **Est-ce que le code marche ?** Est-ce que tu le lancerais toi-même si tu le clonais ?
- **Est-ce que le style est cohérent ?** Les mêmes conventions de nommage que le reste du projet ?
- **Est-ce qu'il y a des erreurs ?** Des typos, des imports manquants, des erreurs de logique ?
- **Est-ce qu'il n'y a pas de secrets dedans ?** Des mots de passe, des API keys, des tokens ?
- **Est-ce que c'est compréhensible ?** Quelqu'un qui voit ce code pour la première fois peut-il suivre ce qui se passe ?
### 3. Donne du feedback
Clique sur une ligne pour ajouter un comment. Sois précis :
**Du bon feedback :**
> Dans `groet.py` ligne 2 : que se passe-t-il si `naam` est vide ? Peut-être ajouter une valeur par défaut ?
**Du mauvais feedback :**
> Ce n'est pas bon.
### 4. Envoie ta review
Clique sur **Review changes**. Tu as trois options :
- **Comment** : juste du feedback, pas de décision.
- **Approve** : le code est bon, il peut être mergé.
- **Request changes** : il faut changer quelque chose avant que la PR puisse être mergée.
Pour ta première review : choisis **Approve** si tout a l'air bon, ou **Request changes** si tu veux faire changer quelque chose.
## Étape 4 : Traiter le feedback (auteur)
Le reviewer a laissé un comment. L'auteur modifie le code :
```bash
# Vérifie que tu es bien sur ta branche feature
git switch feature/groet-functieModifie groet.py sur base du feedback. Par exemple :
def groet(naam="wereld"):
return f"Hallo {naam}!"Committe et pushe :
git add groet.py
git commit -m "Add default parameter to groet function"
git pushLe nouveau commit apparaît automatiquement dans la PR. Le reviewer voit la mise à jour et peut regarder à nouveau.
Si le reviewer a mis Approved, il est temps de merger.
Sur GitHub, dans la PR, tu cliques sur Merge pull request. Choisis Create a merge commit (l’option par défaut). Clique sur Confirm merge.
La branche feature est maintenant fusionnée avec master. Sur GitHub, tu peux supprimer la branche avec le bouton Delete branch qui apparaît après le merge.
En local, tu dois aussi nettoyer :
git switch master
git pull # récupère le merge qui vient d'avoir lieu sur GitHub
git branch -d feature/groet-functie # supprime la branche localeTon master est maintenant up-to-date. Ta branche feature a disparu, en local et sur GitHub. Prêt pour le prochain morceau de travail.
1. git switch -c feature/iets ← Crée une branche feature
2. Travaille, committe, travaille, committe
3. git push -u origin feature/iets ← Push vers GitHub
4. Ouvre une PR sur GitHub ← Demande une review
5. Le reviewer regarde, donne du feedback
6. Modifie le code, committe, pushe ← Traite le feedback
7. Le reviewer a approuvé
8. Merge la PR sur GitHub ← Le code part vers master
9. git switch master && git pull ← Récupère master en local
10. git branch -d feature/iets ← Nettoie la brancheUne review, ce n’est pas : « Ça a l’air bon. » Une bonne review est précise, constructive et respectueuse.
Les questions que tu te poses pendant une review :
Comment donner du feedback :
Commence par ce qui est bien. Sois ensuite précis sur ce qui peut être mieux. Termine par une conclusion claire.
Exemple :
La fonction marche exactement comme décrit. Deux suggestions :
- À la ligne 2 : une valeur par défaut pour
naamserait pratique.- Pense à ajouter une docstring qui explique ce que la fonction retourne.
Pour le reste, ça a l’air bon. Si tu changes ces deux choses, je l’approuve avec plaisir.
Échange ton rôle avec ton buddy et refais tout le workflow une fois : maintenant, c’est toi le reviewer.
Montre à un coach :
master.C’était la dernière session Git. Ce que tu sais faire maintenant :
init, add, commit, log, diff)master (branch, switch, merge)push, pull, clone)Ce n’est pas « en plus ». C’est comme ça que les développeurs travaillent chaque jour. Que tu fasses des jeux, des sites web ou de l’IA : Git et GitHub sont les outils qui gardent ton projet sous contrôle. Utilise-les.
good first issue. Forke le repo, fais un fix et ouvre une PR.Tu connais peut-être HTML par internet : <h1>, <p>, <a>. Mais pour des notes et de la documentation, HTML demande beaucoup trop de frappe. C’est pour ça que Markdown existe.
Markdown est un mini-langage que tu écris en texte normal. Ça reste lisible sans devoir d’abord le convertir. Et d’une seule pression sur un bouton, ça devient du HTML propre : des titres, des listes, des liens, des tableaux.
Dans cette session, tu apprends toute la base de Markdown. À la fin, tu écriras des notes qui ont l’air professionnelles, sur GitHub, dans Obsidian, ou dans n’importe quel autre programme qui comprend Markdown.
Markdown est partout :
README.md en Markdown. Les issues, les pull requests, les wikis : tout est en Markdown..md.Le grand avantage : tu écris du texte normal. Pas de tags compliqués. Et le résultat reste toujours lisible, même en texte brut.
Les fichiers Markdown se terminent par .md. Crée-en un :
mkdir mijn-notities
cd mijn-notities
echo "# Ma première note" > test.mdTu peux ouvrir des fichiers .md dans n’importe quel éditeur de texte : le Bloc-notes, VS Code, Thonny, Obsidian. VS Code a une preview intégrée : clique en haut à droite sur l’icône avec la loupe et le livre.
Tu fais des titres avec #. Plus il y a de #, plus le titre est petit :
# Ceci est un titre (h1)
## Ceci est un sous-titre (h2)
### Ceci est un titre plus petit (h3)
#### Encore plus petit (h4)Tu fais un paragraphe en tapant simplement du texte. Une ligne vide entre les deux commence un nouveau paragraphe :
Ceci est le premier paragraphe. Il continue comme ça.
Ceci est le deuxième paragraphe. Parce qu'il y a une ligne vide entre les deux.Astuce : tu n’utilises # qu’une seule fois par document : pour le titre. Le reste commence à ##.
**Ceci est en gras**
*Ceci est en italique*
~~Ceci est barré~~
Tu peux aussi **mettre du *gras* et de l'italique ensemble** dans la même phrase.Le résultat :
**gras** devient gras*italique* devient italique~~barré~~ devient Attention : pas d’espaces entre les astérisques et le texte. ** gras ** ne marche pas. **gras** oui.
Certains éditeurs acceptent aussi les underscores : __gras__ et _italique_. Mais les astérisques sont le standard : utilise-les.
Tu fais une ligne horizontale avec trois tirets (ou plus) :
---Ou avec des astérisques :
***Le résultat est une ligne sur toute la largeur. Utilise-le avec parcimonie : une ou deux par document, c’est assez. Trop de lignes rendent tes notes brouillonnes.
Utilise -, * ou + :
- Python
- Git
- Markdown
- GitHubTu peux imbriquer des listes en indentant (2 ou 4 espaces) :
- Langages de programmation
- Python
- JavaScript
- Gestion de versions
- Git
- GitHub1. Ouvre Thonny
2. Écris ton code
3. Clique sur RunPeu importe les numéros que tu tapes : Markdown numérote automatiquement. Ceci :
1. Étape un
1. Étape deux
1. Étape trois…donne exactement le même résultat que 1, 2, 3. Pratique si tu veux ajouter une étape plus tard sans tout renuméroter.
- [x] Installer Git
- [x] Faire ton premier commit
- [ ] Apprendre les branches
- [ ] Ouvrir une pull request[x] est coché, [ ] est ouvert. Ça marche dans les issues GitHub, les pull requests, et beaucoup d’applis de notes.
[clique ici pour le site CoderDojo](https://python.coderdojohasselt.be)Le mot entre [ ] est le texte cliquable. L’URL entre ( ) est la destination.
[Voir la session 11](11-git-intro/)Ça fait un lien vers le fichier 11-git-intro/_index.md dans le même dossier.
<https://github.com>Ça montre l’URL comme lien cliquable, sans texte séparé.
Une image, c’est presque la même chose qu’un lien, mais avec un ! devant :
Le texte entre [ ] est le texte alt : il apparaît si l’image ne charge pas, ou il est lu par les screen readers.
Images et Git : Les petites images (SVG, petits PNG), tu peux les mettre dans Git. Les grosses images (>1 MB) et les vidéos, mieux vaut éviter, parce qu’elles ralentissent ton repo.
| Commande | Ce qu'elle fait |
|----------|-------------|
| `git init` | Créer un nouveau dépôt |
| `git add` | Préparer des fichiers pour le commit |
| `git commit` | Enregistrer les modifications |
| `git push` | Envoyer les commits vers GitHub |Les caractères | forment les colonnes. La ligne --- sépare l’en-tête des données. Le : dans la ligne de séparation détermine l’alignement :
| Aligné à gauche | Centré | Aligné à droite |
|:-----------------|:-----------:|------------------:|
| gauche | milieu | droite |Utilise des backticks pour de courts bouts de code dans une phrase :
Utilise `git status` pour voir ce qui a changé.Pour plusieurs lignes de code, tu utilises trois backticks :
```python
def groet(naam):
return f"Hallo {naam}!"
```La langue (python) derrière les premiers backticks donne du syntax highlighting. Ça marche pour des dizaines de langues : bash, html, css, javascript, json, yaml, markdown.
```
Ceci est juste du texte
sans syntax highlighting
```Utilise > pour des citations ou des remarques importantes :
> Git n'est pas un back-up. Git est une machine à remonter le temps.
> Quelqu'un sur internetPlusieurs lignes > à la suite forment un seul bloc. Une ligne > vide commence un nouveau paragraphe à l’intérieur de la citation.
Un bon README.md combine tout ce que tu connais maintenant. Voici un exemple :
# Mon projet
Une courte description de ce que fait ce projet.
## Installation
```bash
git clone https://github.com/jouw-naam/mijn-project.git
cd mijn-project
```
## Utilisation
1. Ouvre `main.py` dans Thonny.
2. Clique sur **Run**.
3. Choisis un niveau et démarre.
## Ce que tu apprends
- [x] Bases de Pygame Zero
- [x] Collision detection
- [ ] Système de highscore
- [ ] Effets sonores
## Liens
- [CoderDojo Hasselt](https://coderdojohasselt.be)
- [Code source sur GitHub](https://github.com/jouw-naam/mijn-project)| Quoi | Markdown |
|---|---|
| Titre niveau 1 | # Titre |
| Titre niveau 2 | ## Sous-titre |
| Titre niveau 3 | ### Titre plus petit |
| Gras | **gras** |
| Italique | *italique* |
| Barré | ~~barré~~ |
| Ligne horizontale | --- ou *** |
| Liste (non ordonnée) | - item |
| Liste (numérotée) | 1. item |
| Checklist | - [ ] item ouvert |
| Lien | [texte](url) |
| Image |  |
| Code inline | `code` |
| Bloc de code | ```langue |
| Citation | > citation |
| Tableau | | colonne | colonne | |
Montre à un coach et à un buddy :
Markdown est simple, mais il est partout. Tes README sur GitHub, tes notes dans Obsidian, ta documentation : tout devient plus lisible avec Markdown. Utilise-le. N’en fais pas trop avec la mise en forme. De bonnes notes sont claires, pas chargées.
README.md pour ton projet Python préféré. Utilise des titres, une liste et un bloc de code.