Snake : Notes du coach

Objectif du défi

Un ninja a terminé le défi si :

  • ✅ Basic : le serpent se déplace avec les flèches, mange des fruits, grandit et affiche le score.
  • ⭐ Stretch : game over en cas de collision avec un mur ou avec lui-même ; un écran de game over avec le score ; redémarrage avec R.
  • 🔥 Expert : la vitesse augmente à mesure que le score monte ; le meilleur score reste affiché après un redémarrage ; un fruit n’apparaît jamais sur le serpent.

Préparation

  • Donne le code de départ au ninja. Il contient main.py et le dossier images/ avec les images de fruits.
  • Les commandes, la fenêtre et le chronométrage sont déjà en place. Le ninja remplit nieuw_fruit(), zet_stap() et teken().
  • Vérifie que pygame est disponible sur l’ordinateur portable (voir Installer Thonny).

Nouveau concept : charger et redimensionner des images

C’est la première fois que les ninjas chargent et redimensionnent une image. Le code de départ le fait déjà, mais explique-le si un ninja le demande :

surf = pygame.image.load('images/apple.png').convert_alpha()
fruit_images['apple'] = pygame.transform.scale(surf, (TILE, TILE))
  • pygame.image.load() lit le fichier PNG et le charge comme une Surface.
  • .convert_alpha() fait en sorte que la transparence fonctionne correctement.
  • pygame.transform.scale() renvoie une nouvelle Surface à la taille demandée. L’original ne change pas.
  • screen.blit(surf, (x, y)) dessine la Surface à la position (x, y).

Questions fréquentes

« Le serpent va trop vite » clock.tick(60) tourne 60 fois par seconde. Un pas par frame, c’est beaucoup trop rapide. Le code de départ utilise pygame.time.get_ticks() pour mesurer si assez de temps s’est écoulé. Vérifie que le ninja n’appelle zet_stap() que si nu - laatste_stap >= STAP_MS.

« Le serpent peut aller en arrière » La direction ne peut jamais être inversée directement. Le code de départ le vérifie déjà dans le gestionnaire d’événements (if event.key == pygame.K_UP and dy == 0). Si le ninja a écrit les commandes lui-même, montre-lui cette vérification.

« Le serpent ne grandit pas quand il mange un fruit » À chaque pas, tu supprimes le dernier élément (slang.pop()). Quand le serpent mange un fruit, tu sautes ce pop(). Vérifie que le ninja saute bien le pop() lors d’une collision avec un fruit.

« Un fruit apparaît sur le serpent » Le ninja fait apparaître un fruit sans vérifier si la position est déjà occupée. Indice : utilise une boucle while qui répète tant que pos in slang.

« La collision avec lui-même n’est pas détectée » nieuw_hoofd in slang correspond aussi à la tête actuelle (le premier élément avant le déplacement). Utilise nieuw_hoofd in slang[1:].

« Le texte du score ne s’affiche pas » font.render() renvoie une Surface. Il faut encore la mettre à l’écran avec screen.blit(). Beaucoup de ninjas oublient la deuxième étape.


Indices par niveau

Donne ces indices quand un ninja bloque. Pas de code complet.

✅ Basic

  • Enregistre la direction sous forme de deux nombres (dx, dy), par ex. (1, 0) pour la droite.
  • À chaque pas : calcule nieuw_hoofd = (slang[0][0] + dx, slang[0][1] + dy), ajoute-le à l’avant, supprime le dernier.
  • Grandir : saute slang.pop() si la nouvelle tête est égale à fruit_pos. Appelle ensuite nieuw_fruit().
  • Afficher du texte : tekst = font.render(f"Score: {score}", True, ZWART) + screen.blit(tekst, (6, 4)).

⭐ Stretch

  • Après avoir calculé la nouvelle tête, vérifie : hors de la grille ? Dans slang[1:] ? Alors game_over = True et return.
  • Redémarrage : intercepte pygame.K_r dans le gestionnaire d’événements si game_over vaut True, puis appelle reset().

🔥 Expert

  • Vitesse : STAP_MS = max(60, BASISINTERVAL - score * 10). Au score 9, l’intervalle n’est plus que de 60 ms. Recalcule-le à chaque fois avant de vérifier.
  • Meilleur score : garde-le en dehors de reset(). Mets-le à jour seulement si score > hoogste_score.
  • Pas de fruit sur le serpent : while True: pos = ...; if pos not in slang: break.