Mise en œuvre d'un système de score et d'interface utilisateur avec Pygame

L'ajout d'un système de score est essentiel pour transformer un prototype de jeu en une expérience interactive complète. Cet article détaille comment suivre et afficher dynamiquement le score, le record, le niveau actuel et le nombre de vies restantes dans un jeu développé avec Pygame.

1. Initialisation des données statistiques

Pour suivre l'évolution du score, nous devons d'abord mettre à jour la classe chargée de stocker l'état du jeu. Le score doit être réinitialisé à chaque nouvelle partie, il est donc placé dans la méthode de réinitialisation.

class StatsJeu:
    """Gère le suivi des statistiques du jeu."""
    
    def __init__(self, ai_game):
        self.settings = ai_game.settings
        self.reset_stats()
        # Le record ne doit jamais être réinitialisé
        self.high_score = 0

    def reset_stats(self):
        """Initialise les données changeantes durant la partie."""
        self.vaisseaux_restants = self.settings.limite_vaisseaux
        self.score = 0
        self.niveau = 1

2. Création de l'interface du tableau de bord

La classe TableauScore est responsable de la transformation des données numériques en images textuelles affichables à l'écran. Elle utilise le module pygame.font pour le rendu du texte.

import pygame.font
from pygame.sprite import Group
from ship import Ship

class TableauScore:
    """Classe dédiée à l'affichage des informations de jeu."""

    def __init__(self, ai_game):
        self.screen = ai_game.screen
        self.screen_rect = self.screen.get_rect()
        self.settings = ai_game.settings
        self.stats = ai_game.stats

        # Configuration de la police
        self.text_color = (40, 40, 40)
        self.font = pygame.font.SysFont(None, 42)

        # Préparation des images initiales
        self.preparer_score()
        self.preparer_record()
        self.preparer_niveau()
        self.preparer_vaisseaux(ai_game)

    def preparer_score(self):
        """Transforme le score en image formatée."""
        score_arrondi = round(self.stats.score, -1)
        score_str = "{:,}".format(score_arrondi)
        self.score_image = self.font.render(score_str, True, self.text_color, self.settings.bg_color)

        # Positionnement en haut à droite
        self.score_rect = self.score_image.get_rect()
        self.score_rect.right = self.screen_rect.right - 20
        self.score_rect.top = 20

3. Gestion des collisions et mise à jour des points

Pour que le score soit réactif, nous devons intercepter les collisions entre les projectiles et les ennemis. Chaque ennemi détruit doit rapporter un nombre de points défini dans les paramètres.

def _verifier_collisions_projectiles(self):
    """Gère les impacts entre balles et ennemis."""
    collisions = pygame.sprite.groupcollide(self.projectiles, self.ennemis, True, True)

    if collisions:
        for ennemis_touches in collisions.values():
            self.stats.score += self.settings.points_ennemi * len(ennemis_touches)
        self.sb.preparer_score()
        self.sb.verifier_nouveau_record()

4. Formatage du score et records

Pour un aspect "Arcade", nous arrondissons le score à la dizaine la plus proche en utilisant round(valeur, -1). Le record est géré de manière persistante durant la session de jeu.

def verifier_nouveau_record(self):
    """Vérifie si un record a été battu."""
    if self.stats.score > self.stats.high_score:
        self.stats.high_score = self.stats.score
        self.preparer_record()

def preparer_record(self):
    """Génère l'image du record actuel."""
    record_str = "{:,}".format(round(self.stats.high_score, -1))
    self.record_image = self.font.render(record_str, True, self.text_color, self.settings.bg_color)

    # Centrage horizontal en haut de l'écran
    self.record_rect = self.record_image.get_rect()
    self.record_rect.centerx = self.screen_rect.centerx
    self.record_rect.top = self.score_rect.top

5. Progression des niveaux

Lorsque la flotte ennemie est entièrement détruite, le joueur passe au niveau suivant. La difficulté augmente et le multiplicateur de points peut également être ajusté.

def preparer_niveau(self):
    """Convertit le niveau en image."""
    niveau_str = str(self.stats.niveau)
    self.niveau_image = self.font.render(niveau_str, True, self.text_color, self.settings.bg_color)

    # Positionnement sous le score actuel
    self.niveau_rect = self.niveau_image.get_rect()
    self.niveau_rect.right = self.score_rect.right
    self.niveau_rect.top = self.score_rect.bottom + 10

6. Affihcage graphique des vies restantes

Plutôt que d'afficher un simple chiffre, il est plus intuitif de représenter les vies restantes par des icônes du vaissaeu. Pour ce faire, nous créons un groupe de sprites simplifié.

def preparer_vaisseaux(self, ai_game):
    """Affiche le nombre de vaisseaux restants graphiquement."""
    self.vaisseaux = Group()
    for numero_vaisseau in range(self.stats.vaisseaux_restants):
        vaisseau = Ship(ai_game)
        vaisseau.rect.x = 10 + numero_vaisseau * vaisseau.rect.width
        vaisseau.rect.y = 10
        self.vaisseaux.add(vaisseau)

def afficher_tout(self):
    """Dessine tous les éléments du tableau de bord sur l'écran."""
    self.screen.blit(self.score_image, self.score_rect)
    self.screen.blit(self.record_image, self.record_rect)
    self.screen.blit(self.niveau_image, self.niveau_rect)
    self.vaisseaux.draw(self.screen)

Enfin, assurez-vous d'apeler TableauScore.afficher_tout() dans votre boucle principale de rendu, juste après avoir dessiné les éléments de jeu mais avant de rafraîchir l'écran via pygame.display.flip(). Cela garantit que l'interface utilisateur apparaît toujours au-dessus du gameplay.

Étiquettes: Python Pygame game-development UI-Design scoring-system

Publié le 6 juillet à 00h36