Intégrer des sons dans un jeu de casse-brique avec Python et Pygame

Introduction

L’ajout de sons dans un jeu vidéo améliore grandement l'expérience utilisateur en le rendant plus immersif et interactif. Les jeux développés avec Pygame en Python ne font pas exception : l’intégration de sons pour les événements comme les collisions entre la balle, la raquette, les briques, ou les rebonds sur les murs, peut donner vie au jeu.

Dans cet article, nous allons voir comment ajouter des sons dans un jeu de casse-brique en utilisant Pygame. Nous allons déclencher différents sons pour chaque type de collision, rendant ainsi le jeu plus dynamique.


1. Initialisation du module audio de Pygame

Avant d’ajouter des sons, il est nécessaire d’initialiser le module mixer de Pygame, qui est responsable de la gestion de l'audio. Il s’agit d’une étape indispensable pour pouvoir charger et jouer des fichiers audio.

1.1. Initialiser le module mixer

Le module pygame.mixer est responsable de la lecture des sons dans Pygame. Vous devez l'initialiser avant d'utiliser des sons. Ensuite, vous pouvez charger les fichiers audio avec pygame.mixer.Sound().

Code : Initialiser le module audio et charger des fichiers :

import pygame

# Initialiser le module mixer pour gérer les sons
pygame.mixer.init()

# Charger les sons pour les collisions avec la raquette, les briques, et les murs
son_brique = pygame.mixer.Sound("son_brique.ogg")
son_raquette = pygame.mixer.Sound("son_raquette.wav")
son_mur = pygame.mixer.Sound("son_mur.wav")

1.2. Formats de fichiers audio supportés

Pygame prend en charge plusieurs formats de fichiers audio comme .wav et .ogg. Il est recommandé d’utiliser ces formats pour garantir la compatibilité avec tous les systèmes.


2. Jouer les sons lors des collisions

Une fois les fichiers audio chargés, vous pouvez jouer les sons en utilisant la méthode play() de l’objet Sound. Nous allons associer chaque son à un type de collision : balle-contre-raquette, balle-contre-brique, ou balle-contre-mur.

2.1. Son pour la collision avec la raquette

Lorsqu'une balle touche la raquette, nous allons jouer un son pour signaler l’impact.

Code : Jouer un son lors de la collision avec la raquette :

def check_collision(self, raquette):
    if self.rect.colliderect(raquette.rect):
        self.speed_y = -self.speed_y  # Inverser la direction
        son_raquette.play()  # Jouer le son pour la collision avec la raquette

2.2. Son pour la destruction des briques

Lorsque la balle casse une brique, un autre son est joué pour rendre cet événement plus visible.

Code : Jouer un son lors de la destruction d'une brique :

def check_collision_briques(self, briques):
    for brique in briques:
        if self.rect.colliderect(brique.rect):
            briques.remove(brique)  # Supprimer la brique touchée
            self.speed_y = -self.speed_y  # Inverser la direction de la balle
            create_particles(brique.rect.x + brique.width // 2, brique.rect.y + brique.height // 2)  # Générer des particules
            son_brique.play()  # Jouer le son lors de la destruction de la brique
            break

2.3. Son pour les collisions avec les murs

Lorsque la balle touche un mur (gauche, droite, ou haut), un son distinct est joué.

Code : Jouer un son lorsque la balle touche un mur :

def move(self):
    self.rect.x += self.speed_x
    self.rect.y += self.speed_y

    # Rebonds sur les murs
    if self.rect.left <= 0 or self.rect.right >= SCREEN_WIDTH:
        self.speed_x = -self.speed_x
        son_mur.play()  # Jouer le son lorsque la balle touche le mur
    if self.rect.top <= 0:
        self.speed_y = -self.speed_y

3. Exemple final avec sons intégrés

Voici un exemple complet qui intègre tous les sons lors des collisions avec les différents éléments du jeu.

Code complet du programme de casse-brique avec sons :

import pygame
import sys
import numpy as np
from numba import jit

# Nombre maximum de particules
MAX_PARTICLES = 500

# Positions et vitesses des particules
particles_pos = np.zeros((MAX_PARTICLES, 2))
particles_vel = np.zeros((MAX_PARTICLES, 2))
particles_life = np.zeros(MAX_PARTICLES)
GRAVITE = 9.8

# Initialiser le module mixer pour les sons
pygame.mixer.init()

# Charger les sons
son_brique = pygame.mixer.Sound("son_brique.wav")
son_raquette = pygame.mixer.Sound("son_raquette.wav")
son_mur = pygame.mixer.Sound("son_raquette.wav")

# Fonction optimisée avec Numba pour mettre à jour les particules
@jit(nopython=True)
def update_particles(positions, velocities, lifetimes, delta_time):
    for i in range(len(lifetimes)):
        if lifetimes[i] > 0:
            velocities[i][1] += GRAVITE * delta_time  # Appliquer la gravité à la vitesse en y
            velocities[i][0] += np.random.uniform(-0.05, 0.05)  # Dispersion horizontale
            positions[i] += velocities[i] * delta_time  # Mettre à jour la position
            lifetimes[i] -= delta_time  # Réduire la durée de vie

def create_particles(x, y):
    for i in range(100):  # Génère 100 particules par brique
        for j in range(MAX_PARTICLES):
            if particles_life[j] <= 0:  # Trouver une particule inactive
                particles_pos[j] = [x, y]
                particles_vel[j] = np.random.uniform(-200, 200, 2)  # Vitesse aléatoire initiale
                particles_life[j] = 2.0  # Durée de vie en secondes
                break

# Classe Raquette
class Raquette:
    def __init__(self):
        self.width = 100
        self.height = 20
        self.x = (SCREEN_WIDTH - self.width) // 2
        self.y = SCREEN_HEIGHT - 50
        self.speed = 10
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)

    def move(self, keys):
        if keys[pygame.K_LEFT] and self.rect.left > 0:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT] and self.rect.right < SCREEN_WIDTH:
            self.rect.x += self.speed

    def draw(self, screen):
        pygame.draw.rect(screen, (0, 0, 255), self.rect)

# Classe Balle
class Balle:
    def __init__(self):
        self.radius = 10
        self.x = SCREEN_WIDTH // 2
        self.y = SCREEN_HEIGHT // 2
        self.speed_x = 5
        self.speed_y = -5
        self.rect = pygame.Rect(self.x - self.radius, self.y - self.radius, self.radius * 2, self.radius * 2)

    def check_collision_briques(self, briques):
        for brique in briques:
            if self.rect.colliderect(brique.rect):
                briques.remove(brique)  # Supprimer la brique touchée
                self.speed_y = -self.speed_y  # Inverser la direction de la balle après collision
                create_particles(brique.rect.x + brique.width // 2, brique.rect.y + brique.height // 2)  # Générer des particules
                son_brique.play()  # Jouer le son lorsque la brique est détruite
                break

    def move(self):
        self.rect.x += self.speed_x
        self.rect.y += self.speed_y

        # Rebonds sur les murs
        if self.rect.left <= 0 or self.rect.right >= SCREEN_WIDTH:
            self.speed_x = -self.speed_x
            son_mur.play()  # Jouer le son lorsque la balle touche le mur
        if self.rect.top <= 0:
            self.speed_y = -self.speed_y

    def draw(self, screen):
        pygame.draw.circle(screen, (255, 0, 0), (self.rect.x + self.radius, self.rect.y + self.radius), self.radius)

    def check_collision(self, raquette):
        if self.rect.colliderect(raquette.rect):
            self.speed_y = -self.speed_y
            son_raquette.play()  # Jouer le son lorsque la balle touche la raquette

# Le reste du programme (classe Brique, boucle principale) reste inchangé.


# Classe Brique
class Brique:
    def __init__(self, x, y):
        self.width = 80
        self.height = 30
        self.rect = pygame.Rect(x, y, self.width, self.height)

    def draw(self, screen):
        pygame.draw.rect(screen, (0, 0, 0), self.rect)

# Créer plusieurs briques
def creer_briques():
    briques = []
    for row in range(5):  # 5 lignes de briques
        for col in range(10):  # 10 colonnes
            brique = Brique(col * 80 + 10, row * 30 + 10)
            briques.append(brique)
    return briques

# Initialiser Pygame
pygame.init()

# Dimensions de la fenêtre
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Casse-Brique")

# Couleurs
WHITE = (255, 255, 255)
RED = (255, 0, 0)

# Initialiser l'horloge pour contrôler le FPS
clock = pygame.time.Clock()

# Initialiser les objets du jeu
raquette = Raquette()
balle = Balle()
briques = creer_briques()

# Boucle principale
running = True
while running:
    clock.tick(60)  # Limite à 60 FPS
    delta_time = clock.get_time() / 1000.0  # Temps écoulé par frame

    keys = pygame.key.get_pressed()

    # Gestion des événements
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # Déplacement de la raquette
    raquette.move(keys)

    # Déplacement de la balle
    balle.move()

    # Vérification des collisions
    balle.check_collision(raquette)
    balle.check_collision_briques(briques)

    # Mettre à jour les particules
    update_particles(particles_pos, particles_vel, particles_life, delta_time)

    # Effacer l'écran et dessiner les éléments
    screen.fill(WHITE)
    raquette.draw(screen)
    balle.draw(screen)

    # Dessiner les briques
    for brique in briques:
        brique.draw(screen)

    # Dessiner les particules
    for i in range(MAX_PARTICLES):
        if particles_life[i] > 0:
            pygame.draw.circle(screen, RED, (int(particles_pos[i][0]), int(particles_pos[i][1])), 3)

    pygame.display.flip()

pygame.quit()

Conclusion

L’ajout de sons dans un jeu améliore considérablement l'expérience utilisateur, rendant les interactions plus engageantes. En utilisant Pygame, vous pouvez facilement intégrer des sons pour des événements spécifiques comme les collisions ou la destruction d'objets. Assurez-vous d’utiliser des fichiers audio compatibles avec Pygame et de bien équilibrer le volume pour éviter toute perturbation de l'expérience de jeu.

L’intégration des sons dans un jeu de casse-brique est un excellent moyen d’ajouter de l’immersion sans trop alourdir la logique du jeu.

Lien vers le son de la brique qui se casse.

Lien vers le son de la balle qui rebondit.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *