Dojo Defender : Session 1

Ton vaisseau spatial a atterri dans l’espace sombre. Il est temps de le faire vivre. Dans cette session, tu ajoutes un vaisseau que tu contrôles et tu fais tomber des astéroïdes. Évite-les ou perds une vie. Combien de temps tu survis ?

Ce que tu vas apprendre aujourd’hui

  • Utiliser des listes pour garder plusieurs astéroïdes
  • Spawner des objets et les supprimer
  • Détecter des collisions avec colliderect
  • Tenir les vies à jour et afficher un effet d’explosion
  • Forcer le game over quand tes vies sont épuisées

Étape 0 : Installation

  1. Ouvre Thonny.
  2. Télécharge le starter Dojo Defender, décompresse le ZIP et ouvre main.py.
  3. Clique sur Run. Tu vois un écran bleu foncé avec ton vaisseau spatial en bas. Tu sais déjà le déplacer avec les flèches.
  4. Des problèmes ? Va voir Installer Thonny.

Étape 1 : Fais apparaître des astéroïdes

Un jeu sans danger, c’est ennuyeux. Ajoute une liste qui garde tous les astéroïdes, et une fonction qui crée de nouveaux astéroïdes :

# en haut, après WIDTH et HEIGHT :
asteroids = []

def spawn_asteroid():
    rock = Actor('asteroid_big')
    rock.x = random.randint(30, WIDTH - 30)
    rock.y = -30
    rock.speed = random.uniform(3, 5)
    asteroids.append(rock)

Tu as aussi besoin de import random en haut du fichier. Ajoute cette ligne.

Appelle la fonction dans update() avec un compteur pour qu’un astéroïde n’apparaisse pas à chaque frame :

# en haut, en dehors des fonctions :
timer = 0

def update():
    global timer
    timer += 1
    if timer % 60 == 0:   # chaque seconde (60 frames)
        spawn_asteroid()

Mets ça avant le code de mouvement du vaisseau.

Étape 2 : ✅ Basic : faire tomber les astéroïdes et les dessiner

Les astéroïdes doivent tomber vers le bas et disparaître quand ils sortent de l’écran :

def update():
    global timer
    timer += 1
    if timer % 60 == 0:
        spawn_asteroid()

    for rock in asteroids[:]:      # [:] = une copie pour supprimer sans risque
        rock.y += rock.speed
        if rock.y > HEIGHT + 30:
            asteroids.remove(rock)

N’oublie pas de dessiner les astéroïdes dans draw() :

def draw():
    screen.fill((10, 10, 30))
    for rock in asteroids:
        rock.draw()
    ship.draw()

Étape 3 : ⭐ Stretch : collision + vies

Quand un astéroïde touche ton vaisseau, tu perds une vie. Ajoute lives et game_over en haut :

lives = 3
game_over = False

Ajoute la détection de collision dans la boucle for :

    for rock in asteroids[:]:
        rock.y += rock.speed

        if rock.y > HEIGHT + 30:
            asteroids.remove(rock)
        elif rock.colliderect(ship):
            asteroids.remove(rock)
            global lives, game_over
            lives -= 1
            if lives <= 0:
                game_over = True

Affiche les vies et le score dans draw() :

    screen.draw.text(f"Score : {score}", (10, 10), color="white", fontsize=24)
    screen.draw.text(f"Vies : {lives}", (10, 40), color="red", fontsize=24)

Arrête le jeu quand game_over est True :

def update():
    if game_over:
        return
    ...

Affiche un écran de game over dans draw() :

    if game_over:
        screen.draw.text(
            "GAME OVER",
            center=(WIDTH / 2, HEIGHT / 2),
            color="red",
            fontsize=60,
        )
        screen.draw.text(
            f"Score final : {score}",
            center=(WIDTH / 2, HEIGHT / 2 + 60),
            color="white",
            fontsize=30,
        )

Étape 4 : 🔥 Expert : explosions + invisibilité

Quand un astéroïde te touche, tu veux voir une explosion au lieu de voir le vaisseau disparaître comme ça. Utilise les quatre frames d’explosion (explosion_1 à explosion_4) :

explosion = Actor('explosion_1')
explosion_active = False
explosion_frame = 0
explosion_timer = 0

En cas de collision : cache le vaisseau, lance l’explosion :

        elif rock.colliderect(ship):
            asteroids.remove(rock)
            global lives, game_over, explosion_active, explosion_frame, explosion_timer
            lives -= 1

            explosion.pos = (ship.x, ship.y)
            explosion.image = 'explosion_1'
            explosion_frame = 1
            explosion_timer = 5
            explosion_active = True
            ship.visible = False

            if lives <= 0:
                game_over = True

Fais jouer l’explosion dans update() :

    if explosion_active:
        explosion_timer -= 1
        if explosion_timer <= 0:
            explosion_frame += 1
            if explosion_frame > 4:
                explosion_active = False
                ship.visible = True
                ship.pos = (WIDTH / 2, HEIGHT - 50)
            else:
                explosion.image = f'explosion_{explosion_frame}'
                explosion_timer = 5

Ajoute ensuite une période d’invisibilité pour ne pas être touché à nouveau tout de suite :

invincible = False
invincible_timer = 0

Dans update() :

    if invincible:
        invincible_timer -= 1
        if invincible_timer <= 0:
            invincible = False
            ship.visible = True

Adapte la vérification de collision :

        elif rock.colliderect(ship) and not invincible and ship.visible:

Dessine l’explosion dans draw() :

    if explosion_active:
        explosion.draw()

Showcase

Montre ton Dojo Defender à un coach et à un buddy. Combien de temps tu survis ? Tu as des explosions ? Ça a de la gueule ?

À la prochaine !

« La prochaine fois : ton vaisseau RÉPLIQUE. Des ennemis en formation, et toi tu les exploses au laser. Ça va être épique. »

À emporter chez toi

Essaie une de ces extensions à la maison :

  1. Son — Ajoute sounds/explosion.wav quand un astéroïde explose (sounds.explosion.play()).
  2. Plus difficile — Fais tomber les astéroïdes plus vite à mesure que le score monte : rock.speed = random.uniform(3 + score // 10, 5 + score // 10).
  3. Power-up — Ajoute un power-up vert rare qui donne une vie en plus.
  4. Plus petit — Utilise asteroid_med ou asteroid_small pour varier la taille et la vitesse.

Télécharger Dojo Defender