Développement d'un jeu Snake en Python avec la bibliothèque Turtle

Implémentation du jeu Snake en Python

Cet article décrit le processus de développement d'un jeu Snake en utilisant Python et la bibliothèque Turtle, avec des fonctionnalités telles que le déplacement du serpent, la gestion des scores, la génération d'obstacles et la détection des collisions.

Configuration initiale de la fenêtre de jeu

La bibliothèque Turtle est utilisée pour créer une intefrace graphique simple. Voici comment configurer la fenêtre :

import turtle
import random

fenetre = turtle.Screen()
fenetre.title("Jeu Snake")
fenetre.bgcolor("noir")
fenetre.setup(width=600, height=600)
fenetre.tracer(0)  # Désactive le rafraîchissement automatique pour éviter le scintillement

La méthode tracer(0) est essentielle pour contrôler manuellement le rafraîchissement de l'écran, améliorant ainsi les performances.

Initialisation des éléments du jeu

Le serpent est composé d'une tête et d'un corps stocké dans une liste. La nourriture et les obstacles sont créés comme des objets Turtle séparés.

# Tête du serpent
tete = turtle.Turtle()
tete.speed(0)
tete.shape("square")
tete.color("rouge", "jaune")
tete.penup()
tete.goto(0, 0)
tete.direction = "stop"

# Corps du serpent (liste de segments)
corps = []

# Nourriture
nourriture = turtle.Turtle()
nourriture.speed(0)
nourriture.shape("circle")
nourriture.color("vert")
nourriture.penup()
nourriture.goto(100, 0)

# Score
score = 0
affichage_score = turtle.Turtle()
affichage_score.speed(0)
affichage_score.color("blanc")
affichage_score.penup()
affichage_score.hideturtle()
affichage_score.goto(0, 260)
affichage_score.write("0", align="center", font=("Arial", 24, "normal"))

Logique de déplacement et de contrôle

Le déplacement du serpent est géré par des fonctions qui changent la direction en fonction des touches clavier. La position est mise à jour en incrémentant les coordonnées x ou y.

def deplacer_haut():
    if tete.direction != "bas":
        tete.direction = "haut"

def deplacer_bas():
    if tete.direction != "haut":
        tete.direction = "bas"

def deplacer_gauche():
    if tete.direction != "droite":
        tete.direction = "gauche"

def deplacer_droite():
    if tete.direction != "gauche":
        tete.direction = "droite"

def mouvement():
    if tete.direction == "haut":
        y = tete.ycor()
        tete.sety(y + 20)
    elif tete.direction == "bas":
        y = tete.ycor()
        tete.sety(y - 20)
    elif tete.direction == "gauche":
        x = tete.xcor()
        tete.setx(x - 20)
    elif tete.direction == "droite":
        x = tete.xcor()
        tete.setx(x + 20)

Gestion de la croissance du corps

Lorsque le serpent mange la nourriture, un nouveau segment est ajouté au corps. La logique de déplacement du corps consiste à faire suivre chaque segment par le précédent.

def verifier_nourriture():
    global score
    if tete.distance(nourriture) < 20:
        # Placer la nourriture aléatoirement sur une grille de 20 pixels
        x_nourriture = 20 * random.randint(-14, 14)
        y_nourriture = 20 * random.randint(-14, 14)
        nourriture.goto(x_nourriture, y_nourriture)

        # Ajouter un segment au corps
        nouveau_segment = turtle.Turtle()
        nouveau_segment.speed(0)
        nouveau_segment.shape("square")
        nouveau_segment.color("jaune", "vert")
        nouveau_segment.penup()
        if len(corps) == 0:
            nouveau_segment.goto(tete.xcor(), tete.ycor())
        else:
            nouveau_segment.goto(corps[-1].xcor(), corps[-1].ycor())
        corps.append(nouveau_segment)

        score += 1
        affichage_score.clear()
        affichage_score.write(str(score), align="center", font=("Arial", 24, "normal"))

def deplacer_corps():
    for i in range(len(corps) - 1, 0, -1):
        corps[i].goto(corps[i-1].xcor(), corps[i-1].ycor())
    if len(corps) > 0:
        corps[0].goto(tete.xcor(), tete.ycor())

Détection des collisions

Le jeu détecte les collisions avec les limites de la fenêtre, le corps du serpent et les obstacles. Pour les limites, le serpent traverse l'écran en réapparaissant de l'autre côté.

def collision():
    # Traversée des limites
    if tete.xcor() > 280:
        tete.setx(-280)
    elif tete.xcor() < -280:
        tete.setx(280)
    if tete.ycor() > 280:
        tete.sety(-280)
    elif tete.ycor() < -280:
        tete.sety(280)

    # Collision avec le corps
    for segment in corps:
        if tete.distance(segment) < 20:
            return True

    # Collision avec les obstacles (si implémentés)
    for obstacle in liste_obstacles:
        if tete.distance(obstacle) < 20:
            return True

    return False

Gestion des états du jeu et obstacles

Pour ajouter des fonctionnalités avancées comme des menus et des cartes, une machine à états est utilisée. Les obstacles sont créés dynamiquement en fonction de la carte choisie.

# États du jeu
MENU = 0
JEU_EN_COURS = 1
JEU_TERMINE = 2
etat_jeu = MENU

liste_obstacles = []

def creer_obstacle(x, y):
    obstacle = turtle.Turtle()
    obstacle.speed(0)
    obstacle.shape("square")
    obstacle.color("gris")
    obstacle.penup()
    obstacle.goto(x, y)
    liste_obstacles.append(obstacle)

def creer_carte(choix_carte):
    for obs in liste_obstacles:
        obs.clear()
        obs.hideturtle()
    liste_obstacles.clear()

    if choix_carte == 1:
        for x in range(-280, 280, 20):
            if abs(x) > 20:
                creer_obstacle(x, 0)
    elif choix_carte == 2:
        for x in range(-280, 140, 20):
            creer_obstacle(x, 40)
        for y in range(80, 280, 20):
            creer_obstacle(120, y)

Boucle principale du jeu

La boucle principale utilise ontimer pour exécuter les mises à jour à intervalles réguliers, permettant un contrôle fluide du déroulement du jeu.

def demarrer_jeu(choix_carte):
    global etat_jeu
    creer_carte(choix_carte)
    tete.showturtle()
    nourriture.showturtle()
    etat_jeu = JEU_EN_COURS

def partie():
    global etat_jeu
    if etat_jeu == JEU_EN_COURS:
        deplacer_corps()
        mouvement()
        if collision():
            etat_jeu = JEU_TERMINE
            tete.hideturtle()
            nourriture.hideturtle()
            for segment in corps:
                segment.hideturtle()
        else:
            verifier_nourriture()
    fenetre.update()
    fenetre.ontimer(partie, 50)

# Liaison des touches
fenetre.listen()
fenetre.onkeypress(deplacer_haut, "Up")
fenetre.onkeypress(deplacer_bas, "Down")
fenetre.onkeypress(deplacer_gauche, "Left")
fenetre.onkeypress(deplacer_droite, "Right")
fenetre.onkeypress(lambda: demarrer_jeu(1), "1")
fenetre.onkeypress(lambda: demarrer_jeu(2), "2")

partie()
fenetre.mainloop()

Problèmes rencontrés et solutions

Pendant le développement, plusieurs défis ont été surmontés, notamment :

  • Mouvement du corps : L'initialisation correcte de la logique de suivi a résolu le problème où les segments se superposaient.
  • Génération de nourriture : L'utilisation d'une grille de 20 pixels a assuré que la nourriture s'aligne avec le mouvement du serpent.
  • Gestion des collisions : La traversée des limites a été ajustée pour éviter les blocages aux bords de l'écran.
  • Performence : L'optimisation du rafraîchissement avec tracer(0) a amélioré la fluidité du jeu.

Étiquettes: Python Turtle Snake Game Game Development Collision Detection

Publié le 4 juin à 01h18