Una buena forma de enriquecer un mundo es añadirle efectos sonoros y música ambiente. En Aetheria Game Engine es sencillo conseguir esto, mediante código BeanShell. AGE soporta una gran variedad de formatos de audio y música para este propósito.
Un fichero de audio es aquél que guarda una grabación digital de sonido. Son la manera más general y más utilizada de representar sonidos, porque en ellos podemos tener almacenados efectos, música, voces, o cualquier otro tipo de sonido.
El soporte de audio de AGE permite utilizar mayor variedad de formatos de audio que otros sistemas, y permite tocar sonidos, detenerlos, repetirlos en bucle y cambiar dinámicamente el volúmen de forma muy sencilla.
Los formatos de audio actualmente soportados por AGE son: WAV, AIFF, MP3, OGG y SPX (nótese que AGE también soporta música en MIDI y MOD; pero éstos no son formatos de audio y su manejo se hace con otros métodos distintos, que se explican más adelante).
Los sonidos se pueden reproducir y gestionar directamente desde métodos de la clase Mobile
, de forma que para que un jugador escuche un sonido en su cliente, invocaremos los métodos directamente sobre ese jugador.
/*clase Mobile*/ boolean playAudioIfAvailable ( URL sound )
m.playAudioIfAvailable( sound )
toca el sonido referenciado por sound
en el cliente asociado con la criatura m
(que normalmente será un jugador), si esto es posible.
En el caso de que sea posible y el cliente del jugador tenga el volumen activado, comenzará a sonar el audio y el método devolverá inmediatamente true
(sin esperar a que la reproducción termine).
En el caso de que no sea posible reproducir el sonido, no sonará nada y el método devolverá false
. Esto puede suceder por las siguientes razones:
Cabe recordar que para obtener el objeto de la clase URL que apunta a un fichero que incluimos con el mundo, podemos utilizar el método getResource()
de la clase World
. Así, para reproducir un sonido llamado “musica.ogg” que incluimos con el mundo, haríamos:
jugador.playAudioIfAvailable( world.getResource("musica.ogg") );
Nótese que en este caso estamos ignorando el valor de retorno (true
o false
) porque no nos importa: simplemente queremos que si el jugador está jugando en un cliente que soporta sonido, pueda oírlo, y si no, tampoco pasa nada. El valor de retorno sólo será importante si queremos programar algún comportamiento alternativo para clientes que no tengan sonido.
/*clase Mobile*/ boolean playAudioIfAvailable ( URL sound , int loopTimes )
Este método hace lo mismo que boolean playAudioIfAvailable ( URL sound )
; pero nos permite especificar a mayores un parámetro entero loopTimes
que sirve para hacer que un sonido se repita un determinado número de veces:
loopTimes
veces,stopAudioIfAvailable()
, que se verá más abajo)./*clase Mobile*/ boolean playAudioIfAvailable ( URL sound , int loopTimes , boolean fade )
Este método hace lo mismo que boolean playAudioIfAvailable ( URL sound , int loopTimes )
; pero nos permite especificar un parámetro booleano adicional fade
. Si este parámetro se pone a true
, el sonido se reproducirá con un “fade in” (transición de inicio). Si se pone a false
, el método se comportará igual que la versión sin este parámetro.
/*clase Mobile*/ boolean stopAudioIfAvailable ( URL sound )
m.stopAudioIfAvailable( sound )
para la reproducción del sonido referenciado por sound
en el cliente asociado con la criatura m
(que normalmente será un jugador), si este sonido se encuentra sonando.
En el caso de que el sonido esté sonando, además de detenerlo, el método devuelve true
. Si no está sonando (bien porque no ha llegado a reproducirse o porque ya ha terminado su reproducción), el método no tiene efecto y devuelve false
.
/*clase Mobile*/ boolean stopAudioIfAvailable ( URL sound , boolean fade )
Este método hace lo mismo que boolean stopAudioIfAvailable ( URL sound )
; pero nos permite especificar un parámetro booleano adicional fade
. Si este parámetro se pone a true
, el sonido se reproducirá con un “fade out” (transición de final). Si se pone a false
, el método se comportará igual que la versión sin este parámetro.
/*clase Mobile*/ boolean setAudioGainIfAvailable ( URL sound , double gain )
m.setAudioGainIfAvailable ( sound , gain )
permite cambiar el volumen del sonido referenciado por sound
que esté sonando en el cliente asociado con la criatura m
(que normalmente será un jugador), si esto es posible. El volumen toma el valor gain
, que ha de estar entre 0.0 y 1.0, siendo 0.0 el volumen nulo (sin sonido) y 1.0 el volumen máximo. El método devolverá true
si el volumen se ha podido cambiar, y false
de lo contrario.
Nótese que para cambiar el volumen, el sonido tiene que estar sonando. Sin embargo, podemos cambiar el volumen de un sonido desde el principio llamando inmediatamente a setAudioGainIfAvailable
después de playAudioIfAvailable
:
jugador.playAudioIfAvailable( world.getResource("musica.ogg") ); jugador.setAudioGainIfAvailable( world.getResource("musica.ogg") , 0.2 );
Como nada más lanzar el sonido ya llamamos al cambio de volumen, el efecto de este código será que el audio “musica.ogg” se reproduzca con volumen 0.2.
Si en lugar de llamar a setAudioGainIfAvailable
inmediatamente lo llamamos más adelante, con el sonido a medias, el volumen cambiará dinámicamente.
Supongamos que queremos parar un sonido que estaba sonando (sonido1.mp3) y comenzar a reproducir otro (sonido2.mp3) con volumen 0.5. Entonces, haríamos lo siguiente:
//parar un sonido si está tocando jugador.stopAudioIfAvailable( world.getResource("sonido1.mp3") ); //tocar un sonido, si existe el fichero y el jugador usa un cliente que soporta audio jugador.playAudioIfAvailable( world.getResource("sonido2.mp3") ); jugador.setAudioGainIfAvailable( world.getResource("sonido2.mp3") , 0.5 );
Cabe destacar que también es posible reproducir varios sonidos a la vez. Esto puede ser interesante si, por ejemplo, tenemos un sonido de música ambiente pero queremos que además se produzcan efectos sonoros al llevar a cabo acciones.
Los ficheros de música MIDI (con extensión .mid
) son archivos que, en lugar de almacenar una grabación de sonido (como los ficheros de audio), guardan música en forma de una partitura que el ordenador puede reproducir.
Esta manera de representar la música es mucho más limitada que los ficheros de audio, porque no se guarda una representación fidedigna de los sonidos sino sólo notas y orientaciones sobre a qué instrumento corresponden, y suele suceder que la interpretación de esos instrumentos suena de manera muy distinta dependiendo de la tarjeta de sonido, sistema operativo y configuración de cada máquina. Por otra parte, la ventaja que tienen los ficheros MIDI es que ocupan mucho menos espacio que los ficheros de audio.
Los métodos para reproducir y detener música MIDI en AGE son similares a los correspondientes al audio, aunque proporcionan menos funcionalidad:
Por todo esto, en general sólo es recomendable utilizar música en formato MIDI en AGE en casos en los que sea necesario que el mundo ocupe poco espacio en disco. De lo contrario, es mucho más recomendable usar formatos de audio: en caso de duda, siempre audio, ya que es más flexible, suena mejor y es más fiable.
/*clase Mobile*/ boolean playMidiIfAvailable ( URL sound )
m.playMidiIfAvailable( sound )
toca el fichero MIDI por sound
en el cliente asociado con la criatura m
(que normalmente será un jugador), si esto es posible.
En el caso de que no sea posible reproducir la música, no sonará nada y el método devolverá false
. Esto puede suceder por las siguientes razones:
También puede suceder que no se pueda reproducir la música porque esté sonando otra (como ya se ha dicho, sólo se puede reproducir un fichero MIDI a la vez). En este caso, el comportamiento depende del sistema operativo y de la configuración: puede ser que el método se niegue a reproducir el sonido y devuelva false
, o bien que se pare el sonido anterior y empiece a sonar el nuevo, o bien incluso que se paren los dos. Por lo tanto, lo más razonable es no intentar reproducir nunca dos MIDIs a la vez, ya que no hay garantía de que el comportamiento vaya a ser el mismo en una máquina que en otra.
/*clase Mobile*/ boolean playMidiIfAvailable ( URL sound , int loopTimes )
Este método hace lo mismo que boolean playMidiIfAvailable ( URL sound )
; pero nos permite especificar a mayores un parámetro entero loopTimes
que sirve para hacer que una música en MIDI se repita un determinado número de veces:
loopTimes
veces,stopMidiIfAvailable()
, que se verá más abajo)./*clase Mobile*/ boolean stopMidiIfAvailable ( )
m.stopMidiIfAvailable( sound )
para la música MIDI que esté sonando en el cliente asociado con la criatura m
(que normalmente será un jugador).
En el caso de que algún MIDI esté sonando, además de detenerlo, el método devuelve true
. Si no está sonando (bien porque no ha llegado a reproducirse o porque ya ha terminado su reproducción), el método no tiene efecto y devuelve false
.