Añadiendo puntuaciones en Asteroides

A modo de ejemplo se va a implementar la posibilidad de guardar las mejores puntuaciones obtenidas en Asteroides. Se utilizarán mecanismos alternativos que serán desarrollados a lo largo de este capítulo y el siguiente:

  • Array (implementado en el CAPÍTULO 3)
  • Preferencias
  • Ficheros en memoria interna
  • Fichero en memoria externa
  • Fichero en recursos
  • XML con SAX
  • JSON con GSon
  • JSON con JSon
  • Base de datos SQLite relacionales
  • Content Provider
  • Internet a través de sockets
  • Servicios Web


Para facilitar la sustitución del método de almacenamiento en el capítulo 3 se ha creado la siguiente interfaz en la aplicación Asteroides:

public interface AlmacenPuntuaciones {
   public void guardarPuntuacion(int puntos, String nombre, long fecha);
   public Vector<String> listaPuntuaciones(int cantidad);
}

También se declaró la variable almacen de tipo AlmacenPuntuaciones y se ha creado la actividad Puntuaciones que visualizaba un ListView con las puntuaciones. Dado que en capítulo  3 todavía no teníamos la opción de jugar, no se podían añadir nuevas puntuaciones a almacen. En el siguiente ejercicio tratremos de calcular una puntuación en el juego y almacenarla en almacen.

Ejercicio paso a paso: Calculando la puntuación en Asteroides

1.     Crea una variable global en la clase VistaJuego que se llame puntuacion e inicialízala a cero:

private int puntuacion = 0;

2.     Cada vez que se destruya un asteroide hay que incrementar esta variable. añade dentro de destruyeAsteroide() la siguiente línea:

puntuacion += 1000;

3.     Cuando desde la actividad inicial Asteroides, se llame a la actividad Juego  nos interesa que esta nos devuenva la puntuación obtenida. Recuerda como en el Capítulo 3 hemos estudiado la comunicación entre actividades. Para pasar la información entre las actividades añade en siguiente código en Asteroides en sustitución del método lanzarJuego() anterior:

public void lanzarJuego(View view) {
   Intent i = new Intent(this, Juego.class);
   startActivityForResult(i, 1234);
}

@Override protected void onActivityResult (int requestCode,
                                    int resultCode, Intent data){
   super.onActivityResult(requestCode, resultCode, data);
   if (requestCode==1234 && resultCode==RESULT_OK && data!=null) {
      int puntuacion = data.getExtras().getInt("puntuacion");
      String nombre = "Yo";
      // Mejor leer nombre desde un AlertDialog.Builder o preferencias
      almacen.guardarPuntuacion(puntuacion, nombre,
                                    System.currentTimeMillis());
      lanzarPuntuaciones(null);
   }
}

4.     Para realizar la respuesta de la actividad va a ser más sencillo hacerlo desde VistaJuego que desde  Juego. El problema es que esta clase es una vista, no una actividad. Para solucionar el problema puedes usar el siguiente truco. Introduce en VistaJuego el siguiente código:

private Activity padre;
 
public void setPadre(Activity padre) {
    this.padre = padre;
}

5.     Cuando se detecte una condición de victoria o derrota es un buen momento para almacenar la puntuación y salir de la actividad. Para ello, crea el siguiente método dentro de VistaJuego:

private void salir() {
   Bundle bundle = new Bundle();
   bundle.putInt("puntuacion", puntuacion);
   Intent intent = new Intent();
   intent.putExtras(bundle);
   padre.setResult(Activity.RESULT_OK, intent);
   padre.finish();
}

6.     Al final del método destruyeAsteroide() introduce:

if (asteroides.isEmpty()) {
          salir();
}

7.     Al final del método actualizaFisica() introduce:

for (Grafico asteroide : asteroides) {
    if (asteroide.verificaColision(nave)) {
       salir();
    }
}

8.     En el método onCreate de Juego introduce:

vistaJuego.setPadre(this);