Anuncios

Bienvenidos sean a este post, hoy veremos como agregar sonido a nuestro juego pero de una forma diferente a como veniamos haciendolo.

Anuncios
Anuncios

En el caso de hoy seguiremos usando a SoundPool para reproducir nuestros sonidos pero a diferencia de antes usaremos una clase donde tendremos distintos metodos que seran los encargados de reproducir los distintos sonidos, en el post anterior tuvimos un pequeño ejemplo cuando hicimos el metodo para el fin del juego, antes de comenzar a divertirnos con nuestra clase debemos descargar el siguiente archivo:

Anuncios

Una vez descargado el archivo debemos extraer los tres archivos de sonido en nuestra PC, no se olviden donde las dejaron, pasamos a nuestro Android Studio y en sobre la carpeta res hacen Click con el boton derecho y seleccionen New -> Android Resource Directory, aparecera un nuevo cuadro y lo confeccionaran de la siguiente manera:

  • Directory name: raw
  • Resource type: raw
  • Source set: main
Anuncios
Anuncios

El resto debe quedar como aparecio, presionen Ok y con esto tenemos nuevo contenedor para los recursos de sonido, tal como lo vinimos haciendo hasta ahora, ahora debemos volver a donde extrajimos los tres archivos, los seleccionamos y presionamos Ctrl+C para copiarlos, volvemos al Android Studio y sobre la carpeta raw que creamos recien y presionamos Ctrl+V para pegarlos, nos aparecera un nuevo cuadro donde no modifican nada y presionen Ok, procedera a copiarlos y quedara de la siguiente manera

Anuncios
Nota: En este momento sigo utilizando a raw porque tiene mayor compatibilidad entre todos los androids, en cambio los assets con Android algo viejunos no funciona directamente, al final del curso hare un anexo donde explicare como cambiar el manejo de los recursos de raw a assets.
Anuncios

Con esto ya tenemos creados nuestros nuevos recursos de sonido, el proximo paso sera la creacion de la clase que los maneje para eso de vuelta hacemos click con el boton derecho sobre el contenedor donde estan el resto de las clases y seleccionamos New -> Java Class, nos aparecera un nuevo cuadro y lo confeccionaremos de la siguiente manera:

  • Nombre: Sound Engine
  • Tipo: Class
Anuncios

Una vez creada nuestra nueva clase lo siguiente sera modificar el codigo actual generado automaticamente por el siguiente:

package org.example.invasores;

import android.media.SoundPool;

class SoundEngine {
    private SoundPool mSP;
    private int mDisparo_ID = -1;
    private int mAlien_Explosion_ID = -1;
    private int mNave_Explosion_ID = -1;
}
Anuncios

Primero modificamos el tipo de acceso a la clase de publica a privada, luego creamos un objeto de tipo SoundPool para manejar a nuestros y los tres IDs para cada uno de nuestros sonidos, veran que en esto seguimos trabajando como hasta ahora, lo siguiente sera agregar a nuestro constructor:

    SoundEngine(Context contexto){
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            AudioAttributes atributos = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(
                            AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();
            mSP = new SoundPool.Builder()
                    .setMaxStreams(5)
                    .setAudioAttributes(atributos)
                    .build();
        } else {
            mSP = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
        }
        try{
            mDisparo_ID = mSP.load(contexto,R.raw.shoot,0);
            mAlien_Explosion_ID = mSP.load(contexto,R.raw.alien_explosion,0);
            mNave_Explosion_ID = mSP.load(contexto,R.raw.player_explosion,0);
        } catch (Exception e){
            Log.e("Invasores","Ha ocurrido un error con los archivos");
        }
    }
Anuncios
Anuncios

En este caso al igual como vinimos viendo hasta ahora, chequeamos si la version de Android es mayor o igual a LOLLIPOP, en caso de ser verdadero usamos al metodo Builder para primero generar los atributos de nuestro SoundPool y luego usamos el Builder de SoundPool, en el cual definimos el maximo de streams y luego le pasamos los atributos creados anteriormente, pero si la version es menor a esta crea al nuevo SoundPool de la forma tradicional, despues tendremos un bloque try/catch donde nos encargaremos de asignar cada uno de los sonidos a las variables correspondientes, lo hacemos por medio de load, primero pasamos el contexto, luego la ubicacion del recurso y por ultimo la prioridad, el catch lo tenemos para que nos notifique en el log si ocurre algo con los archivos, para completar nuestra clase debemos agregar los siguientes tres metodos:

    void repDisparar(){
        mSP.play(mDisparo_ID,1,1,0,0,1);
    }

    void repJugExplotar(){
        mSP.play(mNave_Explosion_ID,1,1,0,0,1);
    }

    void repAlienExplotar(){
        mSP.play(mAlien_Explosion_ID,1,1,0,0,1);
    }
Anuncios

En esta ocasion los tres metodos se encargaran de las siguientes acciones:

  • La primera es para el disparo de la nave
  • La segunda es para cuando impactan nuestra nave
  • La tercera es para cuando explotan los enemigos
Anuncios

Las tres son exactamente iguales porque usaran a mSP y el metodo play pero lo unico que varia es el ID del sonido que asignamos en el constructor, entonces cada vez que llamemos a algunos de estos metodos se encargara de reproducir el sonido asignado, con esto ya tenemos terminada nuestra clase veamos como quedo su codigo final:

SoundEngine.java

package org.example.invasores;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;

class SoundEngine {
    private SoundPool mSP;
    private int mDisparo_ID = -1;
    private int mAlien_Explosion_ID = -1;
    private int mNave_Explosion_ID = -1;

    SoundEngine(Context contexto){
        if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            AudioAttributes atributos = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(
                            AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();
            mSP = new SoundPool.Builder()
                    .setMaxStreams(5)
                    .setAudioAttributes(atributos)
                    .build();
        } else {
            mSP = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
        }
        try{
            mDisparo_ID = mSP.load(contexto,R.raw.shoot,0);
            mAlien_Explosion_ID = mSP.load(contexto,R.raw.alien_explosion,0);
            mNave_Explosion_ID = mSP.load(contexto,R.raw.player_explosion,0);
        } catch (Exception e){
            Log.e("Invasores","Ha ocurrido un error con los archivos");
        }
    }

    void repDisparar(){
        mSP.play(mDisparo_ID,1,1,0,0,1);
    }

    void repJugExplotar(){
        mSP.play(mNave_Explosion_ID,1,1,0,0,1);
    }

    void repAlienExplotar(){
        mSP.play(mAlien_Explosion_ID,1,1,0,0,1);
    }
}
Anuncios

Nuestro ultimo paso sera la implementacion de esta clase para poder agregar sonidos a nuestro juego, para ello debemos volver a la clase GameEngine y al comienzo donde declaramos nuestras variables y creamos el objeto de GameState agregaremos la siguiente linea:

private SoundEngine mSoundEngine;
Anuncios

Con esto declaramos a nuestro objeto de tipo SoundEngine, la siguiente modificacion sera agregar la siguiente linea dentro del constructor de la clase:

mSoundEngine = new SoundEngine(contexto);
Anuncios

Esta se encarga de crear realmente a nuestro objeto en memoria, y le pasamos el contexto para poder trabajar.

Anuncios
Nota: Recuerden que no podemos usar a this porque implementamos a Iniciador y por eso debemos enviar a contexto.
Anuncios

Nuestra ultima modificacion antes de probarlo sera la modificacion del metodo onTouchEvent de la siguiente manera:

    @Override
    public boolean onTouchEvent(MotionEvent evento){
        mSoundEngine.repDisparar();
        return true;
    }
Anuncios

Esto por ahora hara que cada vez que toquemos la pantalla emita el sonido de disparo, con esto ya podemos probar a nuestro juego pero antes veamos como quedo el codigo de nuestra clase GameEngine:

GameEngine.java

package org.example.invasores;

import android.content.Context;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;

class GameEngine extends SurfaceView implements Runnable, Iniciador {
    private Thread mThread = null;
    private long mFPS;

    private GameState mGameState;
    private SoundEngine mSoundEngine;

    public GameEngine(Context contexto, Point tamano){
        super(contexto);
        mGameState = new GameState(this, contexto);
        mSoundEngine = new SoundEngine(contexto);
    }

    @Override
    public void run(){
        while(mGameState.getThreadCorriendo()){
            long frameInicio = System.currentTimeMillis();
            if (!mGameState.getPausado()){

            }
            long frameActual = System.currentTimeMillis() - frameInicio;
            if (frameActual >= 1){
                final int MILISEGUNDOS = 1000;
                mFPS = MILISEGUNDOS / frameActual;
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent evento){
        mSoundEngine.repDisparar();
        return true;
    }

    public void stopThread(){
        mGameState.detenerTodo();

        try{
            mThread.join();
        } catch (InterruptedException e){
            Log.e("Exception","stopThread" +
                    e.getMessage());
        }
    }

    public void startThread(){
        mGameState.startThread();
        mThread = new Thread(this);
        mThread.start();
    }

    public void desapareceReaparece(){

    }
}
Anuncios

Con todo esto podemos pasar a probar nuestro juego como se ve en el siguiente video

Anuncios

En resumen, hoy hemos implementado el sonido en nuestro juego pero a diferencia de los casos anteriores en lugar de hacer que nuestro GameEngine se encargue de manejarlos lo hacemos a traves de otra clase donde usamos la misma forma pero para esta ocasion usamos un metodo para cada sonido y este sera llamado cuando sea necesario, espero les haya gustado sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios

Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00

Anuncio publicitario