Agregar diferentes sonidos a imágenes random

Hola, como están. Estoy desarrollando una serie de juegos educativos y quería saber como podría hacer para cargar varias imágenes que aparecen de forma aleatoria en pantalla y que al colisionarlas con un personaje (actor) reproduzcan diferentes sonidos.

Me explico mejor y dejo un ejemplo: las imágenes son las letras del abecedario (cada imagen es una letra), y necesito agregarle un sonido a cada una de ellas. Alguien me podría ayudar?

Lo que he hecho es algo como esto:

class Enemigo(pilasengine.actores.Bomba):
	
    def iniciar(self):
        pilasengine.actores.Bomba.iniciar(self)
        self.izquierda = 320
        self.y = random.randint(-210, 210)
        self.radio_de_colision = 35
        rutas_imagenes_malo = [
                'data/consonante/b.png',
                'data/consonante/c.png',
		'data/consonante/d.png',
		'data/consonante/f.png',
		'data/consonante/g.png',
		'data/consonante/h.png',
		'data/consonante/j.png',
                'data/consonante/k.png',
                'data/consonante/l.png',
                'data/consonante/m.png',
                'data/consonante/n.png',
                'data/consonante/p.png',
                'data/consonante/q.png',
                'data/consonante/r.png',
                'data/consonante/s.png',
                'data/consonante/t.png',
                'data/consonante/v.png',
                'data/consonante/w.png',
                'data/consonante/x.png',
                'data/consonante/y.png',
                'data/consonante/z.png',
        ]
        self.imagen = random.choice(rutas_imagenes_malo)

    def actualizar(self):
        self.x -= 5
        pilasengine.actores.Bomba.actualizar(self)

Las consonantes serían los “enemigos” porque en el juego solo deben tomar las vocales. Y en el ejemplo he tomado los atributos de bomba, pero necesito que al colisionar con cada letra se produzca una explosión y un sonido que será el de cada letra.

Hola @Fabian_Montecino, me parece tu enfoque está bastante bien, pienso que armar una clase especial para ese actor y tener listadas todas las consonantes está perfecto.

Lo único que cambiaría es la forma de escoger la imagen, para que sea sencillo hacer corresponder imágenes con sonidos.

Por ejemplo, si en lugar de usar “random.choice”, usás ‘randint’ o ‘pilas.azar’ podrías tener dos listas, una con imágenes y otra con sonidos, así:

imagenes = ['imagenes/a.png', 'imagenes/b.png', etc...
sonidos =  ['sonidos/a.wav',  'sonidos/b.wav',  etc...

# en lugar de 2, se podria poner len(imagenes)
cantidad = 2
indice = pilas.azar(0, cantidad - 1)  # similar a randint

# cargamos la imagen y el sonido al azar
imagen = imagenes[indice]
sonido = pilas.sonidos.cargar(sonidos[indice])

Te paso el código completo que usé de prueba, fijate que tendrías que crear al menos las carpetas “imagenes” y “sonidos” con los archivos .png y .wav para que funcione de una:


import pilasengine

pilas = pilasengine.iniciar()

class Letra(pilasengine.actores.Actor):

    def iniciar(self):
        self.velocidad = self.pilas.azar(1, 3)
        self.x = -300
        self.y = self.pilas.azar(-200, 200)
        self._elegir_imagen_y_sonido()

    def actualizar(self):
        self.x += self.velocidad

    def eliminar(self):
        self._reproducir_sonido()
        # Se invoca la destruccion del actor.
        pilasengine.actores.Actor.eliminar(self)

    def _reproducir_sonido(self):
        self.sonido.reproducir()

    def _elegir_imagen_y_sonido(self):
        imagenes = ['imagenes/a.png', 'imagenes/b.png']
        sonidos = ['sonidos/a.wav', 'sonidos/b.wav']

        # en lugar de 2, se podria poner len(imagenes)
        cantidad = 2
        indice = self.pilas.azar(0, cantidad - 1)

        # cargamos la imagen y el sonido al azar
        self.imagen = imagenes[indice]
        self.sonido = self.pilas.sonidos.cargar(sonidos[indice])


# Genera al protafonista
mono = pilas.actores.Mono()
mono.aprender('moverseConElTeclado')


def eliminar_letra(mono, letra):
    letra.eliminar()

# Definimos las colisiones, pero usando 'etiquetas', asi
# evitamos definir grupos y administrarlos.
pilas.colisiones.agregar('mono', 'Letra', eliminar_letra)



# Gener una letra cada 3 segundos
def crear_letra():
    pilas.actores.Letra()

pilas.tareas.siempre(3, crear_letra)

# Vincula al actor para crearlo usando la forma pilas.actores.Letra
pilas.actores.vincular(Letra)
pilas.ejecutar()

Hola @hugoruscitti ! Muchas gracias por tu ayuda, me anduvo muy bien el ejemplo, solo tuve que convertir los audio de mp3 a wav y cambiar los nombres a las carpetas.

Ahora te hago una consulta respeto de “randint” o “pilas.azar”, utilizando estos métodos puedo hacer que me cargue todas las imágenes del abecedario (a,b,c,d,e,f, etc.) pero que solo cargue los sonidos para las vocales “a, e, i, o, u”…

Hasta el momento probé a poner en una carpeta “imagenes” solo las vocales (a.png, e.png, i.png ,o.png, u.png) y en la carpeta “sonidos” (a.wav, e.wav, i.wav, o.wav, u.wav) y a la variable “cantidad” le asigne “len(imagenes)” como me habías dicho y funciona genial. Pero quise agregar mas letras y dejar solo esos sonidos y me aparece un error.
Y en realidad lo que necesito es que al colisionar con las vocales aparezca su sonido, pero al tocar una consonante explote como el actor bomba o haga humo o algún efectos similar.

Pensé en generar otra clase para las letras consonantes con “pilas.azar” pero que cada imagen herede los atributos del actor “bomba”, lo que no se si será posible.

Hola @Fabian_Montecino, para mí lo mas sencillo es usar la misma clase, pero cambiando las listas para representar bien a las explosiones, por ejemplo:

imagenes = ['imagenes/a.png', 'imagenes/b.png', 'imagenes/c.png',       'imagenes/d.png', 'imagenes/e.png']
sonidos = ['sonidos/a.wav',   'sonidos/bomba.wav', 'sonidos/bomba.wav', 'sonidos/bomba.wav', 'sonidos/e.wav']

Luego, para simular la explosión, lo que podrías hacer es tomar el actor y enseñarle la explosión como una habilidad. Por ejemplo, si creas un actor mono desde cero, y querés que pueda explotar podrías escribir lo siguiente:

» mono.aprender('puedeExplotar')
» mono.eliminar()

En tu caso, con la clase Letra, podrías hacer algo así:

class Letra(pilasengine.actores.Actor):

    # Resto de los métodos
    # -----

    def _elegir_imagen_y_sonido(self):
        # codigo anterior ...

        if es_vocal:
            self.aprender('puedeExplotar')
            # al aprender esta habilidad, cuando se elimine va a sonar
            # como bomba y mostrar 

Muchas gracias por tu ayuda Hugo. Saludos!