Páginas

Librería de juegos: FullScreenActivity

Uno de los objetivos que me marco conforme voy haciendo nuevas cosas en Android, es crear una librería con las utilidades que suelo acabar utilizando en la mayoría de mis programas. Así es como nace mi GameLibrary.


Creo que lo primero que añadí a la librería fue la clase FullScreenActivity. Una clase tremendamente sencilla, pero que me ahorra muchas líneas de código. También es verdad que a mí me gusta que todas mis actividades se presenten en pantalla completa, eliminando la barra de título. La clase en cuestión queda así:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class FullScreenActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  requestWindowFeature(Window.FEATURE_NO_TITLE);
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN);
 }
}

Sólo tienes que hacer que una actividad herede de ella para tener una actividad de pantalla completa. Si sólo quieres aplicarlo a alguna clase concreta, mejor copiar las dos líneas de código directamente en ella.

Cuenta atrás

En este post vamos a ver cómo añadir una cuenta atrás a una actividad Android. Este recurso es utilizado con frecuencia en juegos, especialmente cuando la velocidad es importante, para dar al jugador tiempo de preparase para la que se le viene encima.

En el ejemplo vamos a usar una cuenta atrás de 3 a 1, que acabará con un mensaje, y la implementación la haremos con animaciones. Lo primero que necesitaremos serán las imágenes para los números y el mensaje, como por ejemplo:



Una vez colocadas en su sitio (la correspondiente carpeta drawable), las añadiremos todas al layout de nuestra aplicación, en la posición que queramos. Por ejemplo, este código las ubica en el centro de un RelativeLayout.


1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<ImageView
        android:id="@+id/threeImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@drawable/calculator_three_countdown"
        android:visibility="invisible" />
    <ImageView
        android:id="@+id/twoImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@drawable/calculator_two_countdown"
        android:visibility="invisible" />
    <ImageView
        android:id="@+id/oneImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@drawable/calculator_one_countdown"
        android:visibility="invisible" />
    <ImageView
        android:id="@+id/goImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@drawable/calculator_go_countdown"
        android:visibility="invisible" />

Si os fijáis, las hemos marcado todas como invisibles para empezar.

Ahora pasamos al código de la actividad. Como he comentado, vamos a utilizar animaciones. La idea es presentar en orden los números de la cuenta atrás mediante una animación que los haga aparecer. Por tanto, comencemos preparando una animación para mostrar el 3.


1
2
3
4
Animation threeAnim = new ScaleAnimation(0, 1, 0, 1);
threeAnim.setDuration(1000);
findViewById(R.id.threeImage).setVisibility(View.VISIBLE);
findViewById(R.id.threeImage).startAnimation(threeAnim);

Este código deberíamos incluirlo en el método onCreate de la actividad. Lo que hace es crear un objeto ScaleAnimation, que hará crecer el tamaño de la imagen, asignarle una duracion de 1 segundo, y aplicarlo sobre la imagen, tras hacerla visible.

Con todo esto ponemos en marcha la animación. El siguiente paso sería lanzar la animación del 2, en el momento en que termine la del 3. Para esto podemos hacer uso de AnimationListener. Las animaciones Android permiten registrar oyentes, que serán notificados en el momento en que la animación comienza, acaba o se repite, mediante esta interfaz. Podemos hacer que sea directamente nuestra actividad la que implemente AnimationListener. Esto implica que tenemos que definir los siguientes métodos.


1
2
3
4
5
6
@Override
public void onAnimationStart(Animation anim) {}
@Override
public void onAnimationRepeat(Animation anim) {}
@Override
public void onAnimationEnd(Animation anim) {}

El que nos interesa ahora mismo es onAnimationEnd, al que daríamos el siguiente código.

1
2
3
4
5
6
7
8
9
if (anim == threeAnim) {
findViewById(R.id.threeImage).setVisibility(View.GONE);

twoAnim = new ScaleAnimation(0, 1, 0, 1);
twoAnim.setDuration(1000);
twoAnim.setAnimationListener(this);
findViewById(R.id.twoImage).setVisibility(View.VISIBLE);
findViewById(R.id.twoImage).startAnimation(twoAnim);
}

El parámetro anim es la animación que ha terminado; así que, si es la animación del 3, lo que tenemos que hacer es volver a ocultar su imagen, y lanzar la animación del 2.

Lógicamente, para que nuestra actividad sea notificada por las animaciones, tenemos que registrarla como oyente, como se hace en el bloque anterior con twoAnim. El bloque de lanzamiento de threeAnim en onCreate debería completarse para quedar así:

1
2
3
4
5
threeAnim = new ScaleAnimation(0, 1, 0, 1);
threeAnim.setDuration(1000);
threeAnim.setAnimationListener(this);
findViewById(R.id.threeImage).setVisibility(View.VISIBLE);
findViewById(R.id.threeImage).startAnimation(threeAnim);

Además, para poder comprobar qué animación es la que nos está notificando en cada caso, tendremos que definirlas como atributos de la clase, y no como variables locales, como hicimos en el primer bloque.


1
private Animation threeAnim, twoAnim, oneAnim, goAnim;

De esta forma cerraríamos el círculo. Sólo nos falta completar el código de onAnimationEnd para lanzar la animación del 1 al terminar la del 2, y la del mensaje al terminar la del 1. Una vez terminada la animación del mensaje todas las imágenes quedarán ocultas, y tendremos que poner en marcha el contenido real de la actividad.

Esta solución deja abiertas más opciones; por ejemplo, podemos reproducir un sonido en cada paso de la cuenta atrás, añadiendo el código correspondiente en onAnimationStart.

Podéis ver el resultado de esta implementación tanto en Human Calculator como en Fast Tap. Además, aquí os dejo el código completo.

CountdownActivity.java
activity_countdown.xml