Anuncios

Bienvenidos sean a este post, en este post dimos por finalizado nuestro segundo juego de este curso pero hoy volveremos al primero y le agregaremos el sonido para el disparo sin acierto y para la explosion del submarino.

Anuncios

Antes de comenzar primero les recomiendo descargar el siguiente archivo con los dos sonidos:

Anuncios
Nota: Si no tienen el juego pueden hacerlo desde este post.
Anuncios

Una vez descargado, extraigan los dos archivos y tengan los mismos a mano porque pronto los vamos a usar, nuestro siguiente paso es abrir el proyecto con Android Studio, una vez abierto debemos a la carpeta res, hacen click con el boton derecho y eligen New -> Android Resource Directory, aparecera un nuevo cuadro y deberan completar los siguientes campos:

  • Directory Name: raw
  • Resource Type: raw
  • Source Set: main
Anuncios

Una vez generado nuestro nuevo directorio volvemos a donde extrajimos los archivos, los seleccionamos y presionamos Ctrl+C para copiarlos, volvemos al Android Studio, vamos al directorio raw y presionamos Ctrl+V para pegar nuestros archivos, una vez copiados podemos proceder a modificar nuestro codigo en MainActivity, para ello primero agregaremos las variables y el objeto a usar junto con las declaraciones de variables:

    private SoundPool sp;
    private int idDisparo = -1;
    private int idExplosion = -1;
    private int ahoraSonando = -1;
Anuncios

La primer linea crea el objeto encargado de manejar los sonidos por medio de SoundPool, la segunda sera una variable para el id del disparo, la siguiente sera para el id de la explosion y la ultima la usaremos para mas adelante, nuestro siguiente paso sera agregar el siguiente bloque en onCreate para crear nuestro SoundPool dependiendo de la version del Android:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
    AudioAttributes atributos = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .build();
    sp = new SoundPool.Builder()
            .setMaxStreams(5)
            .setAudioAttributes(atributos)
            .build();
} else {
    sp = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
}
Anuncios

En este caso usaremos un condicional donde verifica que la version de Android sea mayor o igual a LOLLIPOP, en caso de ser verdadero primero crear los atributos de audio por medio de Builder y luego creara el objeto tambien con un Builder en lugar de un constructor y utiliza los atributos creados anteriormente, en caso contrario utiliza el constructor habitual donde primero setea el maximo de streams, luego el tipo de contenido y por ultimo la calidad del mismo, nuestro siguiente paso sera agregar el siguiente bloque despues del condicional para cargar los sonidos:

        try{
            idDisparo=sp.load(this,R.raw.Cannon,0);
            idExplosion=sp.load(this,R.raw.Explosion,0);
        } catch (Exception e){
            Log.e("Error","Fallo la carga de los archivos");
        }
Anuncios
Anuncios

En este caso usamos un bloque try/catch para notificarnos en caso de alguna falla pero lo que haremos es cargar cada uno de los archivos en sus respectivas variables, en este caso en el load primero usaremos a this para indicar en que contexto sera, luego ira toda la direccion del recurso, observen como siempre es R, es una constante para indicar que es res, luego ira el nombre del directorio y por ultimo el nombre del recurso es simplemente el archivo sin la extension y por ultimo un valor para la prioridad, nuestra ultima modificacion es agregar el llamado a los sonidos para cada accion, es decir la del disparo para cuando tocamos la pantalla y la explosion para cuando impactamos al submarino, para ello primero debemos agregar esta linea en el metodo disparar:

ahoraSonando=sp.play(idDisparo,1,1,0,0,1);
Anuncios

Lo mas recomendable es agregarla al principio del metodo y esto lo asignaremos a ahoraSonando para tener una referencia en memoria el cual nos sera util a continuacion.

Anuncios

Nuestro siguiente modificacion es en el metodo boom donde agregaremos las siguientes lineas:

        sp.stop(ahoraSonando);
        sp.play(idExplosion,1,1,0,0,1);
Anuncios

En este caso usaremos al metodo stop y le pasaremos a ahoraSonando para que detenga la reproduccion de idDisparo y ejecute la reproduccion de idExplosion, como ambas funciones son las mismas pero lo unico que varia es el id de nuestro sonido, para saber mas sobre esta clase les recomiendo este post, pero resumiendo siempre primero va el id que usamos para cargar el sonido (por medio de load), luego ira el volumen izquierdo, despues el volumen derecho, seguido de la prioridad, la cantidad de veces que lo repetiremos (el valor -1 es para hacerlo infinitamente), y por ultimo el rate, con esto ya podemos pasar a probar nuestro juego como se ve en el siguiente video

Anuncios

En el video vemos los disparos realizados y como finalmente cuando le impactamos al submarino no solo nos notifica en pantalla sino que a su vez escuchamos la explosion, los efectos de sonido los descargue desde este sitio:

https://www.freesoundeffects.com/

Anuncios

Aca podran descargar muchos tipos de efectos para los juegos, hay muchos gratuitos aunque hay muchos mejores pero pagos, antes de finalizar veamos como quedo MainActivity con las recientes modificaciones:

MainActivity.java

package org.example.cazadordesub;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.util.Random;

public class MainActivity extends Activity {
    int numHorPixels;
    int numVerPixels;
    int tamBloque;
    int ancGrilla;
    int altGrilla;
    int vertTocado;
    int horizTocado;
    int subHorPosicion;
    int subVerPosicion;
    boolean impacto;
    int disparos;
    boolean depuracion;
    boolean grilla;
    int alfa;
    int distDesdeSub;
    Display vista;
    Point tamano;

    ImageView juegoVista;
    Bitmap bitmapBlanco;
    Canvas canvas;
    Paint pincel;

    SharedPreferences preferencias;

    private SoundPool sp;
    private int idDisparo = -1;
    private int idExplosion = -1;
    private int ahoraSonando = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button botonI = (Button) findViewById(R.id.inicio);
        Button botonP = (Button) findViewById(R.id.preferencias);
        botonI.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                nuevo();
                dibujar();
            }
        });
        botonP.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                lanzarPreferencias(null);
            }
        });

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            AudioAttributes atributos = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();
            sp = new SoundPool.Builder()
                    .setMaxStreams(5)
                    .setAudioAttributes(atributos)
                    .build();
        } else {
            sp = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
        }
        try{
            idDisparo=sp.load(this,R.raw.cannon,0);
            idExplosion=sp.load(this,R.raw.explosion,0);
        } catch (Exception e){
            Log.e("Error","Fallo la carga de los archivos");
        }

        Log.d("Depurando","En el onCreate");
    }

    public void lanzarPreferencias(View view){
        Intent i = new Intent(this, Preferencias.class);
        startActivity(i);
    }

    void dibujar()
    {
        if (grilla)
            alfa = 255;
        else
            alfa = 0;
        bitmapBlanco = Bitmap.createBitmap(numHorPixels,
                numVerPixels, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmapBlanco);
        juegoVista = new ImageView(this);
        pincel = new Paint();
        setContentView(juegoVista);

        juegoVista.setImageBitmap(bitmapBlanco);
        canvas.drawColor(Color.argb(255,255,255,255));
        pincel.setColor(Color.argb(alfa,0,0,0));
        for(int i=0; i < altGrilla; i++) {
            canvas.drawLine(0, tamBloque * i,
                    numHorPixels - 1, tamBloque * i, pincel);
        }
        for(int i =0; i < ancGrilla; i++){
            canvas.drawLine(tamBloque * i,0,
                    tamBloque * i, numVerPixels -1, pincel);
        }
        pincel.setColor(Color.argb(255,0,0,0));
        canvas.drawRect(horizTocado * tamBloque,
                vertTocado * tamBloque,
                (horizTocado * tamBloque) + tamBloque,
                (vertTocado * tamBloque) + tamBloque,
                pincel);

        pincel.setTextSize(tamBloque * 1.5f);
        pincel.setColor(Color.argb(255,0,0,255));
        canvas.drawText("Disparos realizados: " +
                disparos + " - Distancia del submarino: " +
                distDesdeSub, tamBloque, tamBloque * 1.75f, pincel);

        Log.d("Depurando","En el dibujar()");
        if (depuracion) {
            imprimirDebug();
        }
    }

    void nuevo()
    {
        vista = getWindowManager().getDefaultDisplay();
        preferencias = PreferenceManager.getDefaultSharedPreferences(this);
        tamano = new Point();
        vista.getSize(tamano);
        numHorPixels = tamano.x;
        numVerPixels = tamano.y;
        ancGrilla = 40;
        tamBloque = numHorPixels / ancGrilla;
        altGrilla = numVerPixels / tamBloque;
        disparos = 0;
        distDesdeSub = 0;
        impacto = false;
        depuracion = preferencias.getBoolean("depuracion",false);
        grilla = preferencias.getBoolean("grilla", false);
        Random alazar = new Random();
        subHorPosicion = alazar.nextInt(ancGrilla);
        subVerPosicion = alazar.nextInt(altGrilla);
        horizTocado = -100;
        vertTocado = -100;

        Log.d("Depurando","En el nuevo()");
    }

    void disparar(int x, int y) {
        ahoraSonando=sp.play(idDisparo,1,1,0,0,1);
        disparos++;
        horizTocado = x / tamBloque;
        vertTocado = y / tamBloque;
        impacto = horizTocado == subHorPosicion
                && vertTocado == subVerPosicion;
        int horBrecha = horizTocado - subHorPosicion;
        int verBrecha = vertTocado - subVerPosicion;
        distDesdeSub = (int) Math.sqrt((horBrecha * horBrecha)
                + (verBrecha * verBrecha));
        if (impacto) {
            boom();
        }
        else {
            dibujar();
        }

        Log.d("Depurando","En el disparar()");
    }

    void boom()
    {
        sp.stop(ahoraSonando);
        sp.play(idExplosion,1,1,0,0,1);
        juegoVista.setImageBitmap(bitmapBlanco);
        canvas.drawColor(Color.argb(255,255,0,0));
        pincel.setColor(Color.argb(255,255,255,255));
        pincel.setTextSize(tamBloque * 10);
        canvas.drawText("BOOM!", tamBloque * 4,
                tamBloque * 14, pincel);
        pincel.setTextSize(tamBloque * 2);
        canvas.drawText("Dispara para jugar de nuevo!",
                tamBloque * 8,
                tamBloque * 18, pincel);
        nuevo();

        Log.d("Depurando","Hizo Boom! Verdaderamente");
    }

    void imprimirDebug()
    {
        pincel.setTextSize(tamBloque);
        canvas.drawText("numHorPixels = " + numHorPixels,
                50, tamBloque * 3, pincel);
        canvas.drawText("numVerPixels = " + numVerPixels,
                50, tamBloque * 4, pincel);
        canvas.drawText("tamBloque = " + tamBloque,
                50, tamBloque * 5, pincel);
        canvas.drawText("ancGrilla = " + ancGrilla,
                50, tamBloque * 6, pincel);
        canvas.drawText("altGrilla = " + altGrilla,
                50, tamBloque * 7, pincel);
        canvas.drawText("subHorPosicion = " + subHorPosicion,
                50, tamBloque * 8, pincel);
        canvas.drawText("subVerPosicion = " + subVerPosicion,
                50, tamBloque * 9, pincel);
        canvas.drawText("horizTocado = " + horizTocado,
                50, tamBloque * 10, pincel);
        canvas.drawText("verTocado = " + vertTocado,
                50, tamBloque * 11, pincel);
        canvas.drawText("impacto = " + impacto,
                50, tamBloque * 12, pincel);
        canvas.drawText("depuracion = " + depuracion,
                50, tamBloque * 13, pincel);
        canvas.drawText("grilla = " + grilla,
                50, tamBloque * 14, pincel);
        canvas.drawText("alfa = " + alfa,
                50, tamBloque * 15, pincel);
    }

    @Override
    public boolean onTouchEvent(MotionEvent evento)
    {
        horizTocado = (int)evento.getX();
        vertTocado = (int)evento.getY();
        if ((evento.getAction() &
                MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP){
            disparar(horizTocado,vertTocado);
        }
        Log.d("Depurando","En el onTouchEvent");
        Log.d("Depurando","horizTocado: " + horizTocado);
        Log.d("Depurando","vertTocado: " + vertTocado);
        return true;
    }
}
Anuncios

En resumen, hoy hemos vuelto a implementar a SoundPool pero esta vez para nuestro primer proyecto, hemos vuelto a repetir lo visto anteriormente y tambien logramos dejar una version mas completa de nuestro juego, tienen a disposicion de un sitio para descargar algunos efectos de sonidos gratuitos, tambien pudimos ver como se puede implementar sonidos en proyectos ya creados sin necesidad de tener que volver a crear el mismo, 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