top of page
Buscar

14. Audio: Música y Efectos

  • Foto del escritor: Fernando Sansberro
    Fernando Sansberro
  • 16 nov 2021
  • 12 Min. de lectura

Actualizado: 24 dic 2021

Nuestro juego está tomando forma. En este capítulo vamos a ver como agregar audio al juego. Vamos a ver como se pone una música (o sonido ambiente) de fondo y cómo agregarle efectos de sonido (denominados fx) al juego. Para eso, primero veremos los formatos de audio con los cuales trabaja Pygame y aprenderemos a cargar los archivos de audio y a ejecutarlos en el programa.


El Audio en los Juegos


El audio en un videojuego es tan importante como los gráficos. La música nos pone en el ambiente y ayuda a la inmersión del juego. Los efectos de sonido (llamados sound fx) también son importantísimos en el juego porque nos dan feedback (información) de lo que está pasando en el juego, por ejemplo cuando las cosas colisionan o agarramos una moneda en el juego, siempre hay un sonido para indicarlo y mejorar la experiencia del jugador.


Vamos a ver como cargar el audio para nuestros juegos y cómo manejamos el sonido en Pygame. Al igual que con los gráficos, el audio es realizado utilizando software especializado en audio y generando archivos, que son los que cargaremos en Pygame y reproduciremos cuando ocurran determinados eventos.


Formatos de Archivos de Audio


Los formatos de audio más usados son ogg, mp3 y wav. El formato wav es un formato de audio muy usado, pero tiene la desventaja de que es un formato sin compresión, por lo cual los tamaños de archivo son muy grandes. El formato mp3 es un formato que tiene compresión y es muy popular su uso, pero tiene la desventaja de que no es open source. El formato ogg es un formato de audio parecido al formato mp3 y tiene la ventaja de que es un formato open source.


Pygame puede usar cualquiera de estos formatos de audio mencionados: wav, mp3 y ogg. Es recomendable utilizar el formato ogg cuando se trata de un juego que se va a llevar a varias plataformas. De todas formas es sencillo convertir de un formato a otro utilizando software de edición de audio.


Inicializar el Sistema de Audio


Antes de ejecutar cualquier sonido, debemos inicializar el sistema de audio de Pygame, al cual se le llama mixer. Esta tarea se hará una sola vez, al inicio de nuestro programa y con esto ya podremos cargar y ejecutar sonidos.


Para inicializar el sistema de audio de Pygame, invocamos a la función pygame.mixer.init() inmediatamente después de haber inicializado Pygame. El mixer es el módulo de Pygame que maneja el audio. Entonces, lo primero que hacemos luego de inicializar Pygame, es inicializar el mixer.


Cargar y Ejecutar un Sonido


Una vez que tenemos correctamente inicializado el sistema de audio, cargaremos los sonidos que vamos a usar en el juego. Luego los ejecutaremos cuando ocurran determinados eventos.


Vamos a comenzar poniendo nuestro primer sonido. Haremos que la nave del jugador reproduzca un sonido cuando dispara. Luego de inicializar el sistema de audio, para colocar un nuevo sonido en el juego, se requieren tres pasos:


1) Colocar el archivo de sonido en la carpeta de assets. Los colocaremos en la carpeta assets\audio.

2) Al inicio del juego cargamos el sonido, creando un objeto de la clase pygame.mixer.Sound. Para esto, le pasamos la ruta donde se encuentra el archivo. Ya veremos esto a continuación.

3) Cuando ocurre determinado evento, como por ejemplo, al disparar, se utiliza la función play() en el sonido para ejecutarlo.


Lo que haremos ahora es colocar el primero sonido en el juego, que será el sonido cuando el jugador dispara.


Disparo del Jugador


Comenzaremos con el primer sonido que pondremos en el juego, que será el sonido que se reproduzca cuando el jugador dispare. Abre el ejemplo que se encuentra en la carpeta capitulo_14\001_sonido_al_disparar_jugador y ejecútalo. Verás que al disparar se reproduce un sonido de disparo.


Creamos una carpeta audio debajo de la carpeta assets que será la carpeta en donde vamos a poner los archivos de audio del juego. En la carpeta assets\audio, se encuentra el sonido que vamos a disparar cuando el jugador dispara. Este sonido se encuentra en el archivo player_shoot.wav. Crea la carpeta en tu propio proyecto y copia este archivo.


En el programa principal, main.py, agregamos la llamada a la función para inicializar el sistema de audio de Pygame:


# Función de inicialización.
def init():

   ...

   # Inicializar Pygame.
   pygame.init()

   # Inicializar el mixer de audio de Pygame.
   pygame.mixer.init()

   ...

Luego, en la clase CPlayer, cargaremos el archivo de sonido correspondiente al disparo del jugador en una variable (objeto) que necesitamos para usar el sonido. Para crear un sonido, utilizamos la clase Sound de Pygame y le pasamos como parámetro la ruta del archivo de sonido (en este caso será “assets/audio/player_shoot.wav”).


En el constructor de la clase CPlayer se pone una línea para cargar el sonido y guardarlo en una variable:


def __init__(self, aType):

   # Invocar al constructor de CAnimatedSprite.
   CAnimatedSprite.__init__(self)

   ...

   # Crear el sonido de disparo.
   self.mSoundShoot = pygame.mixer.Sound("assets/audio/player_shoot.wav")

   # Estado inicial.
   self.setState(CPlayer.NORMAL)

Esto cargará el archivo de sonido en memoria, y creamos un objeto de clase Sound (la variable que hemos llamado self.mSoundShoot) que será la variable que usaremos para reproducir el sonido.


Para reproducir el sonido cuando el jugador dispara, debemos identificar en el código dónde es que ocurre el evento. En nuestro juego, ésto ocurre en la función move() de la clase CPlayer (que es por supuesto la clase en la cual pusimos la variable del sonido).


Agregamos una línea cuando se crea la bala del jugador, que dispare el sonido que hemos agregado:


# Movimiento de la nave.
def move(self):

   ...

   # Disparar.
   if fire:
       print("FIRE")
       b = CPlayerBullet()
       b.setXY(self.getX() + self.getWidth() / 2 - b.getWidth() / 2, self.getY())
       b.setVelX(0)
       b.setVelY(-10)
       b.setBounds(0, 0, CGameConstants.SCREEN_WIDTH, CGameConstants.SCREEN_HEIGHT)
       b.setBoundAction(CGameObject.DIE)
       CBulletManager.inst().add(b)

       # Sonido de disparo.
       self.mSoundShoot.play()

De esta forma, una vez que los sonidos están cargados, se pueden disparar en cualquier momento que se desee. Para disparar el sonido en cualquier momento en el juego, se usa el método play() del objeto de la clase Sound que hemos creado (en este caso self.mSoundShoot). Hemos puesto esta variable en la clase CPlayer porque es en esta clase en donde se va a ejecutar el sonido.



Figura 14-1: Ahora el juego tiene sonido al disparar. Se siente mejor.



La mayoría de los sonidos ocurren cuando hay algún evento, como por ejemplo cuando una nave dispara, cuando le pegan a un objeto y explota, cuando se agarra un poder (powerup), etc.


Nota: Hay que tener muy prolijo y ordenado el código de forma tal de que sea fácil colocar la línea que ejecuta el sonido.


Agregando Todos los Sonidos al Juego


Cuando colocamos los sonidos en el juego, el proceso siempre es el mismo. Primero se inicializa el sistema de audio, luego se colocan los sonidos en la carpeta de assets, luego se inicializan las variables, cargando los sonidos y por último se ejecutan los sonidos con la función play().


El problema es, que cuando el juego es muy grande, esta tarea de ubicar la línea exacta en donde se dispara el sonido, puede tomar tiempo. Es importantísimo ser muy prolijo a la hora de programar, y de no tener varias ramas que pueden llevar a ejecutar el mismo sonido.


Ahora vamos a agregar todos los efectos de sonido al juego. Cuando llegamos a esta tarea de poner los sonidos, lo que tenemos que hacer es una lista de los sonidos y cuándo es que se ejecutan. Entonces, la lista para este juego quedará así:



Archivo de Sonido: Evento:

player_shoot.wav Cuando el jugador dispara una bala.

player_hit.wav Cuando al jugador lo toca una bala y parpadea.

player_explosion.wav Cuando el jugador explota.

enemy_shoot Cuando un enemigo dispara.

enemy_explosion.wav Cuando el enemigo explota al tocarlo una bala.


Figura 14-1: La tabla con los sonidos a poner en el juego.



Para armar la lista de sonidos necesarios, debemos pensar en el juego y hacer la lista de los eventos que ocurren. Esto básicamente es una tarea mental, imaginándote estar jugando al juego en tu cabeza y anotar los sonidos.

Los sonidos casi siempre van asociados a las colisiones entre los objetos y a los eventos (disparar, saltar, agarrar objetos, etc).


Colocamos estos archivos de sonido en la carpeta assets/audio y cargamos los sonidos en las clases CNave y CPlayer. Luego, ponemos en el código las llamadas a play() en el lugar que corresponda al evento.


Veamos el ejemplo ubicado en la carpeta capitulo_14\002_todos_los_sonidos. En la carpeta assets\audio hemos ubicado los archivos de sonido. Copia estos archivos a tu propio proyecto.


Al inicio de la clase cargamos los sonidos y luego ubicamos la sentencia play() donde corresponda para ejecutar el sonido. A continuación se muestra en negrita en el código de CPlayer las líneas agregadas. En la función init() se crean los sonidos:


def __init__(self, aType):

   # Invocar al constructor de CAnimatedSprite.
   CAnimatedSprite.__init__(self)

   ...

   # Crear el sonido de disparo.
   self.mSoundShoot = pygame.mixer.Sound("assets/audio/player_shoot.wav")
   # Sonido de hit (cuando le pegan).
   self.mSoundHit = pygame.mixer.Sound("assets/audio/player_hit.wav")
   # Sonido de explosión.
   self.mSoundExplosion = pygame.mixer.Sound("assets/audio/player_explosion.wav")

   # Estado inicial.
   self.setState(CPlayer.NORMAL)

En la función setState(), ubicamos las líneas que disparan los sonidos. Es muy probable que los sonidos ocurran cuando hay un cambio de estado, como es el caso cuando explota o cuando va a morir el jugador. Si armamos el código en forma prolija y se pasa de estado con la función setState(), es muy sencillo agregar sonidos:


def setState(self, aState):
   CAnimatedSprite.setState(self, aState)

   # Por defecto poner el sprite visible.
   self.setVisible(True)

   if self.getState() == CPlayer.NORMAL:
       self.initAnimation(self.mFrames, 0, 0, False)
       self.gotoAndStop(0)

   elif self.getState() == CPlayer.DYING:
       self.stopMove()
       self.initAnimation(self.mFrames, 0, 0, False)
       self.gotoAndStop(0)

       # Ejecutar sonido de morir.
       self.mSoundHit.play()

   elif self.getState() == CPlayer.EXPLODING:
       self.initAnimation(self.mFramesExplosion, 0, 2, False)

       # Ejecutar el sonido de la explosión.
       self.mSoundExplosion.play()

   elif self.getState() == CPlayer.START:
       self.initAnimation(self.mFrames, 0, 0, False)
       self.gotoAndStop(0)

De la misma manera, en la clase CNave, agregamos en la función init() la carga de los sonidos y luego ubicamos las líneas para reproducir los sonidos:


def __init__(self, aType):
   CAnimatedSprite.__init__(self)

   ...

   # Crear el sonido de disparo.
   self.mSoundShoot = pygame.mixer.Sound("assets/audio/enemy_shoot.wav")
   # Sonido de explosión.
   self.mSoundExplosion = pygame.mixer.Sound("assets/audio/enemy_explosion.wav")

   # Estado inicial.
   self.setState(CNave.NORMAL)

Luego de creados los sonidos, el sonido de disparo se ejecuta en la función controlFire():


def controlFire(self):
   # Ver si la nave dispara.
   if random.randrange(1, 500) == 1:
       b = CEnemyBullet()
       b.setXY(self.getX() + self.getWidth() / 2 - b.getWidth() / 2, self.getY() + self.getHeight())
       b.setVelX(0)
       b.setVelY(10)
       b.setBounds(0, 0, CGameConstants.SCREEN_WIDTH, CGameConstants.SCREEN_HEIGHT)
       b.setBoundAction(CGameObject.DIE)
       CEnemyManager.inst().add(b)

       # Ejecutar el sonido de disparo.
       self.mSoundShoot.play()

Y por último, el sonido de la explosión se coloca al entrar en ese estado, en la función setState():


def setState(self, aState):
   CAnimatedSprite.setState(self, aState)

   if self.getState() == CNave.NORMAL:
       self.initAnimation(self.mFramesNormal, 0, 0, True)
   elif self.getState() == CNave.EXPLODING:
       self.initAnimation(self.mFramesExplosion, 0, 0, False)
       self.stopMove()

       # Ejecutar el sonido de explosión.
       self.mSoundExplosion.play()

Con esto, terminamos de colocar los efectos de sonido en el juego. Luego de poner los sonidos hay que testear bien el juego porque puede pasar que bajo ciertas condiciones un sonido no se ejecute, o que se ejecute otro. Esto suele ocurrir cuando el código tiene varias ramas o lógica complicada, cosa que conviene minimizar y aprolijar.


Si dejamos el juego corriendo y escuchamos los efectos de sonido, veremos que dos por tres algún sonido no se ejecuta. Esto se debe a la forma en que estamos usando los canales de sonido, y lo corregiremos más adelante en este capítulo.


Agregando la Música


Vamos a agregar una música para el nivel del juego. La música es un archivo de sonido que se ejecuta en forma cíclica (denominado loop). Esto quiere decir que cuando se termina de reproducir la música, ésta comenzará nuevamente desde el inicio, y la banda de sonido está diseñada para que ese momento de loopeo no se note.

.

Veamos el ejemplo ubicado en la carpeta capitulo_14\003_background_music.

Si ejecutamos el juego, escucharemos una música cuando estamos jugando. La música del nivel se encuentra en el archivo music_game.ogg, y se encuentra ubicado en la carpeta assets/audio. Copia este archivo a tu propio proyecto.


Mira el programa main.py, al final de la función init() que es donde se inicializa la música y se reproduce. Para inicializar un archivo de música, utilizamos la clase pygame.mixer.music. El código para inicializar un archivo de música es el siguiente:


# Función de inicialización.
def init():

   ...

   # Inicializar Pygame.
   pygame.init()

   # Inicializar el mixer de audio de Pygame.
   pygame.mixer.init()

   ...

   # Ejecutar la música de background (loop) del juego.
   pygame.mixer.music.load("assets/audio/music_game.ogg")
   pygame.mixer.music.play(-1)
   # Poner el volumen de la música.
   pygame.mixer.music.set_volume(0.5)

La función load() inicializa la música, y recibe como parámetro la ruta donde se encuentra el archivo. Como siempre, ponemos los assets de sonido en la carpeta assets\audio.


La clase pygame.mixer.music es diferente a pygame.mixer.sound en cuanto a que la música es cargada a demanda (a esto se le llama streamed) y nunca se carga entera en memoria. El mixer en Pygame solamente soporta una sola música a la vez. Cuando cargamos sonidos, creamos una variable para cada sonido, pero para la música no usamos variables.


Luego, con la función play() se reproduce la música. A esta función se le pasa -1 como parámetro para que se reproduzca indefinidamente (en loop).


Nota: Recuerda que siempre puedes consultar la documentación de Pygame en el sitio www.pygame.org para ver que otras funciones se pueden utilizar. Por ejemplo, en el caso del audio, es posible manejar el volumen, pausar la música, obtener la posición en la cual se encuentra el reproductor, encolar varias músicas para que se toquen una tras otra, etc. Cada clase de Pygame ofrece más funciones de las que se pueden explicar en este libro.


En el caso que quisiéramos detener la música (por ejemplo al ir a una pausa, o cuando termina el nivel), usamos la función pygame.mixer.music.stop().


Nota: Algunos soportes de audio en Pygame se encuentran limitados en algunas plataformas, lo que podría hacer que se tranque el juego. Se recomienda el uso del formato ogg para los audios.


El Manager de Audio


Como vimos antes, en algunos casos, algún efecto de sonido puede ser que no se reproduzca correctamente. Esto depende del sistema, pero se debe a que no estamos manejando los canales de sonido correctamente.


Cada sonido se reproduce en un determinado canal. Existen varios canales y debemos asegurarnos que cuando ejecutamos un sonido, éste no se dispare en un canal que está siendo usado, porque eso significa que o bien el sonido no se reproducirá, o bien corte el sonido actual para reproducir el nuevo.


Para eso, escribiremos una clase, que llamaremos CAudioManager, que maneje automáticamente los canales, asignando un canal no utilizado a cada sonido que vayamos a reproducir. Esta clase será una clase singleton (para poderla utilizar desde cualquier clase) y tendrá una función play() que recibirá un sonido (por ejemplo, los sonidos que cargamos en CPlayer o en CNave) y la función reproducirá este sonido en un canal libre.


Mira el ejemplo ubicado en la carpeta capitulo_14\004_audio_manager. En la carpeta \api, hemos puesto esta clase. A continuación se muestra el código de la clase CAudioManager:


# -*- coding: utf-8 -*-

#--------------------------------------------------------------------
# Clase CAudioManager.
# Clase para manejar el audio y los canales.
#
# Autor: Fernando Sansberro - Batovi Games Studio
# Proyecto: Hacete tu Videojuego.
# Licencia: Creative Commons. BY-NC-SA.
#--------------------------------------------------------------------

# Importar Pygame.
import pygame

class CAudioManager(object):

   mInstance = None
   mInitialized = False

   mChannels = 8

   def __new__(self, *args, **kargs):
       if (CAudioManager.mInstance is None):
           CAudioManager.mInstance = object.__new__(self, *args, **kargs)
           self.init(CAudioManager.mInstance)
       else:
           print("Cuidado: CAudioManager(): No se debería instanciar más de una vez esta clase. Usar CAudioManager.inst().")
       return CAudioManager.mInstance

   @classmethod
   def inst(cls):
       if (not cls.mInstance):
           return cls()
       return cls.mInstance
  
   def init(self):
       if (CAudioManager.mInitialized):
           return
       CAudioManager.mInitialized = True

       CAudioManager.mChannels = pygame.mixer.get_num_channels()

       # Crear el sonido de disparo del jugador.
       CAudioManager.mSoundShootPlayer = pygame.mixer.Sound("assets/audio/player_shoot.wav")
       # Sonido de hit (cuando le pegan al jugador).
       CAudioManager.mSoundHitPlayer = pygame.mixer.Sound("assets/audio/player_hit.wav")
       # Sonido de explosión del jugador.
       CAudioManager.mSoundExplosionPlayer = pygame.mixer.Sound("assets/audio/player_explosion.wav")
       # Crear el sonido de disparo del enemigo.
       CAudioManager.mSoundShootEnemy = pygame.mixer.Sound("assets/audio/enemy_shoot.wav")
       # Sonido de explosión del enemigo.
       CAudioManager.mSoundExplosionEnemy = pygame.mixer.Sound("assets/audio/enemy_explosion.wav")

   def play(self, aSound):
       CAudioManager.inst().getChannel().play(aSound)

   def getChannel(self):
       c = pygame.mixer.find_channel(True)
       while c is None:
           CAudioManager.mChannels += 1
           pygame.mixer.set_num_channels(CAudioManager.mChannels)
           c = pygame.mixer.find_channel()
       return c
  
   def destroy(self):
       CAudioManager.mInstance = None

       CAudioManager.mSoundShootPlayer = None
       CAudioManager.mSoundHitPlayer = None
       CAudioManager.mSoundExplosionPlayer = None
       CAudioManager.mSoundShootEnemy = None
       CAudioManager.mSoundExplosionEnemy = None

En la función init() se cargan los sonidos del juego, tanto los que ejecuta el jugador como los que ejecuta los enemigos. Los sonidos ya no se cargan en cada clase, sino en esta función,, en forma centralizada.


Nota: esta parte donde se cargan todos los sonidos del juego, luego se va a poner en algún estado de carga inicial del juego (loading). Pero por ahora trabajaremos de esta manera mientras aprendemos a hacer juegos.


Veamos la parte de ejecutar sonidos. Básicamente lo que hace la función play() es usar la función getChannel() de nuestra clase para obtener el primer canal libre. Para eso, se usa la función find_channel() de Pygame. Si no hubiera ningún canal libre (hay ocho disponibles al inicio), se crea uno nuevo usando la función set_num_channels(). La variable CAudioManager.mChannels lleva la cuenta de cuántos canales hay.


Nota: Es importante consultar la documentación de Pygame para ver cómo es que funciona cada una de las funciones de Pygame que estamos usando, que hace internamente, que retorna, qué parámetros espera, etc. Si hacemos esto, entenderemos bastante mejor su funcionamiento. Sin embargo, podemos utilizar el código de los ejemplos, que está bien escrito, aunque como todo, siempre es mejorable o adaptable a futuras necesidades.


Nota: En este libro estamos usando una nomenclatura propia. Las clases comienzan con “C”, las variables con “m”, los argumentos con “a” (parámetros) y las funciones con nomenclatura denominada “camelCase”, comienzan con minúscula y luego cada palabra va con mayúscula. De esta forma, podemos distinguir fácilmente nuestras funciones (por ejemplo “getChanneel()” de las de Pygame (por ejemplo “find_channel()”). Esto es fundamental para entender el código.


Una vez que tenemos implementada la clase CAudioManager, utilizamos su función play() para reproducir sonidos. Por ejemplo, en la clase CPlayer, para reproducir los sonidos, cambiamos la llamada por las siguientes líneas:


...

# Importar Pygame.
import pygame

...

# Importar la clase del manager de audio.
from api.CAudioManager import *

# La clase CPlayer hereda de CAnimatedSprite.
class CPlayer(CAnimatedSprite):

   ...

   # Establece el estado actual e inicializa
   # las variables correspondientes al estado.
   def setState(self, aState):
       CAnimatedSprite.setState(self, aState)

       # Por defecto poner el sprite visible.
       self.setVisible(True)

       if self.getState() == CPlayer.NORMAL:
           self.initAnimation(self.mFrames, 0, 0, False)
           self.gotoAndStop(0)

       elif self.getState() == CPlayer.DYING:
           self.stopMove()
           self.initAnimation(self.mFrames, 0, 0, False)
           self.gotoAndStop(0)

           # Ejecutar sonido de morir.
           CAudioManager.inst().play(CAudioManager.mSoundHitPlayer)

       elif self.getState() == CPlayer.EXPLODING:
           self.initAnimation(self.mFramesExplosion, 0, 2, False)

           # Ejecutar el sonido de la explosión.
           CAudioManager.inst().play(
       CAudioManager.mSoundExplosionPlayer)

       elif self.getState() == CPlayer.START:
           self.initAnimation(self.mFrames, 0, 0, False)
           self.gotoAndStop(0)

   # Movimiento de la nave.
   def move(self):

       ...

       # Disparar.
       if fire:
           print("FIRE")
           b = CPlayerBullet()
           b.setXY(self.getX() + self.getWidth() / 2 - b.getWidth() / 2, self.getY())
           b.setVelX(0)
           b.setVelY(-10)
           b.setBounds(0, 0, CGameConstants.SCREEN_WIDTH, CGameConstants.SCREEN_HEIGHT)
           b.setBoundAction(CGameObject.DIE)
           CBulletManager.inst().add(b)

           # Sonido de disparo.
           CAudioManager.inst().play(CAudioManager.mSoundShootPlayer)

En la clase CNave, también cambiamos las líneas para ejecutar sonidos, de la siguiente manera:


...

# Importar Pygame.
import pygame

...

# Importar la clase del manager de audio.
from api.CAudioManager import *

# La clase CNave hereda de CAnimatedSprite.
class CNave(CAnimatedSprite):

   ...

   def setState(self, aState):
       CAnimatedSprite.setState(self, aState)

       if self.getState() == CNave.NORMAL:
           self.initAnimation(self.mFramesNormal, 0, 0, True)
       elif self.getState() == CNave.EXPLODING:
           self.initAnimation(self.mFramesExplosion, 0, 0, False)
           self.stopMove()

           # Ejecutar el sonido de explosión.
           CAudioManager.inst().play(
                      CAudioManager.mSoundExplosionPlayer)

   # Invocada desde Bullet cuando la Nave es alcanzada por una bala.
   def hit(self):
       if self.getState() == CNave.NORMAL:
           self.setState(CNave.EXPLODING)
           print("NAVE EXPLOTA")

   def controlFire(self):
       # Ver si la nave dispara.
       if random.randrange(1, 500) == 1:
           b = CEnemyBullet()
           b.setXY(self.getX() + self.getWidth() / 2 - b.getWidth() / 2, self.getY() + self.getHeight())
           b.setVelX(0)
           b.setVelY(10)
           b.setBounds(0, 0, CGameConstants.SCREEN_WIDTH, CGameConstants.SCREEN_HEIGHT)
           b.setBoundAction(CGameObject.DIE)
           CEnemyManager.inst().add(b)

           # Ejecutar el sonido de disparo.
           CAudioManager.inst().play(CAudioManager.mSoundShootEnemy)

   ...

Con esto, tenemos terminado el soporte básico para los sonidos y la música del juego. En el siguiente capítulo continuaremos mejorando el juego, haciendo el marcador de puntaje y las vidas, viendo cómo mostrar textos.

 
 
 

Comments


bottom of page