VISITAS:

viernes, 18 de enero de 2013

Splash screen con AndEngine

Cuando una aplicación Android consta de varias ventanas se suele implementar con varias Activity.
Sin embargo, esto no es lo aconsejable.
El caso típico de un juego son al menos cuatro ventanas:

  • Splash screen
  • Menú
  • Opciones
  • Ventana del juego
Y la navegación entre ambas sería la siguiente:

Comienza la splash, la cual desaparece al cabo de unos pocos segundos y aparece automáticamente el menú. Desde el menú se puede acceder a la ventana de opciones (donde se configura el juego) y desde ahí se puede volver otra vez al menú. Y por fin, desde el menú se accede a la ventana del juego.

Lo aconsejable con AndEngine es crear cuatro escenas y pasar de una a otra utilizando:

    engine.setScene(unaEscena);

En este artículo vamos a seguir este patrón y vamos a crear una splash screen. Crearemos una Activity heredando de SimpleBaseGameActivity, crearemos las EngineOptions y por último, crearemos dos escenas: splashScene y menuScene.

En primer lugar, creamos el proyecto Android de forma similar a como se hace en este artículo.

Método onCreateEngineOptions()

Este método es similar al seguido en el ejemplo del artículo anterior:
public static final int CAMERA_WIDTH = 800;
public static final int CAMERA_HEIGHT = 480;
private Camera camera;
@Override
public EngineOptions onCreateEngineOptions() {
this.camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions engineOptions = new EngineOptions(
true, 
ScreenOrientation.LANDSCAPE_FIXED,
new FillResolutionPolicy(),
this.camera);
return engineOptions;
}

Método onCreateResources()

En este método se cargan los recursos para el menú y para la splash screen:


@Override
protected void onCreateResources() {
// Background
this.backgroundTexture = new BitmapTextureAtlas(this.getTextureManager(), 1024, 1024, TextureOptions.BILINEAR);
this.backgroundRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.backgroundTexture, this, "background.png", 0, 0);
this.backgroundTexture.load();
// Splash


this.splashTexture = new BitmapTextureAtlas(this.getTextureManager(), 1024, 500, TextureOptions.BILINEAR);
this.splashRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.splashTexture, this, "splash.jpg", 0, 0);
this.splashTexture.load();
       }

Método onCreateScene()

En este método se crean las dos escenas: la de la splash screen y la del menú. Inicialmente se activa la escena de splash, pero se pone un timeout, transcurrido el cuál, se activa la escena del menú.

@Override
protected Scene onCreateScene() {
// Escena del menú
menuScene = new Scene();

// Background de la escena
Sprite backgroundSprite = new Sprite(0, 0, this.backgroundRegion, getVertexBufferObjectManager());
menuScene.attachChild(backgroundSprite);

// Escena de splash
splashScene = new Scene();

// Background de la splash screen
Sprite splashSprite = new Sprite(0, 0, this.splashRegion, getVertexBufferObjectManager());
splashScene.attachChild(splashSprite);

mEngine.registerUpdateHandler(new TimerHandler(3f, new ITimerCallback() {
@Override
public void onTimePassed(TimerHandler handler) {
mEngine.unregisterUpdateHandler(handler);
splashScene.detachSelf();
mEngine.setScene(menuScene);
}
}));
return splashScene;
}









Hello World con AndEngine

Antes de empezar a hacer este ejemplo con AndEngine, es necesario tener instalado el motor.
Ver Instalación de AndEngine

1. Abrir Eclipse

2. Crear el proyecto Android

    * File > New > Android Application Project
    Name: HelloWorld
    Package: poner un package cualquiera, por ej com.minombre.android.andengine
    Minimum Required SDK: API 8
    Target SDK: API 15
    Compile With: API 15
    Theme: None
    * Pulsar "Next >"
    Desmarcar "Create custom launcher icon"
    Marcar "Create Activity"
    Desmarcar "Mark this project as a library"
    Desmarcar "Create project in workspace"
    Pulsar "Browse..." y elegir un directorio para el proyecto

    * Pulsar "Next >"
    Marcar "Create Activity"
    Seleccionar "BlankActivity"
    * Pulsar "Next >"
    Activity Name: MainActivity
    Layout name: activity_main
    Navigation type: None
    * Pulsar "Finish"

3. Referenciar la librería AndEngine

    Package Explorer
    Proyecto Hello World (botón dcho) > Properties > Android
    Sección Library: Pulsar "Add..." y añadir la librería AndEngine
    Pulsar "OK"

4. Heredar la Activity de SimpleBaseGameActivity

    Package Explorer
    Abrir MainActivity.java
    Extender SimpleBaseGameActivity
    Eliminar los métodos onCreate y otros que se hayan generado.
    Pulsar sobre la bombilla amarilla a la izda de class > Add unimplemented methods
    Se generarán automáticamente los siguientes métodos:
        onCreateEngineOptions()
        onCreateResources()
        onCreateScene()

5. Crear las variables de clase para la cámara:

private Camera camera;
private static final int CAMERA_WIDTH = 800;
private static final int CAMERA_HEIGHT = 480;

6. Implementar el método onCreateEngineOptions:

@Override
public EngineOptions onCreateEngineOptions() {
this.camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
EngineOptions engOptions = new EngineOptions(
true,   // full screen 
ScreenOrientation.LANDSCAPE_FIXED, 
new FillResolutionPolicy(), 
this.camera);
                engOptions.getAudioOptions().setNeedsSound(true);

engOptions.getAudioOptions().setNeedsMusic(true);

return engOptions;
}

Los parámetros de EngineOptions son:
    true: indica que la Activity ocupará toda la pantalla, incluida la barra de estado.
    LANDSCAPE_FIXED: la pantalla se mostrará en horizontal aunque rote el dispositivo
    FillResolutionPolicy: el motor se adapta al tamaño físico de la pantalla. Esto puede suponer que las imágenes se deformen.

7. Implementar el método onCreateScene:

@Override
protected Scene onCreateScene() {
Scene scene = new Scene();
scene.setBackground(new Background(0.098f, 0.62f, 0.66f));
return scene;
}

Scene es una Entity que contiene otras entities como sprites, etc.

8. Implementar onCreateResources

@Override
protected void onCreateResources() {
loadGraphics();
loadFonts();
loadSounds();
  loadMusic();
}

private void loadGraphics() {
}
private void loadFonts() {
}
private void loadSounds() {
}


private void loadMusic() {
}

 9. Cargar los gráficos

Crear un folder en assets:
    Package Explorer
    Directorio "assets"
    New > Folder
    Folder name: gfx
    * Pulsar "Finish"
Copiar una imagen .png en assets/gfx con el explorador de Windows.
Situarse en el package explorer sobre assets y pulsar F5
Crear las variables de clase:
private BitmapTextureAtlas texture;
private ITextureRegion region;
Implementar el método loadGraphics:
private void loadGraphics() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
texture = new BitmapTextureAtlas(getTextureManager(), 128, 128, TextureOptions.DEFAULT);
region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(texture, this, "android.png", 0, 0);
texture.load();
// cuando la textura no sea necesaria: texture.unload();
}

10. Cargar las fuentes

Crear un folder en assets:
    Package Explorer
    Directorio "assets"
    New > Folder
    Folder name: font
    * Pulsar "Finish"
Copiar una fuente .ttf en assets/font con el explorador de Windows (en este enlace hay muchas fuentes ttf para descargar: fuentes )
Situarse en el package explorer sobre assets y pulsar F5
Crear la variables de clase:
private Font font;
Implementar el método loadFonts:
private void loadFonts() {
FontFactory.setAssetBasePath("font/");
final ITexture fTexture = new BitmapTextureAtlas(getTextureManager(), 32, 32, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
font = FontFactory.createFromAsset(getFontManager(), fTexture, getAssets(), "BaroqueScript.ttf", 40, true, Color.BLACK);
font.load();
}

11. Cargar los sonidos

Crear un folder en assets:
    Package Explorer
    Directorio "assets"
    New > Folder
    Folder name: mfx
    * Pulsar "Finish"
Copiar un sonido .ogg en assets/mfx con el explorador de Windows (se recomienda en formato .ogg porque ocupa mucho menos espacio que mp3 por ejemplo).
Situarse en el package explorer sobre assets y pulsar F5
Crear la variables de clase:
private Sound sound;
Implementar el método loadSounds:
 private void loadSounds() { SoundFactory.setAssetBasePath("mfx/"); try { this.sound = SoundFactory.createSoundFromAsset(getEngine().getSoundManager(), this, "risa.ogg"); } catch (IOException e) { Log.e(tag, "loadSounds() " + e.getMessage()); } }


12. Cargar la música

Copiar una cancion .ogg en assets/mfx con el explorador de Windows (se recomienda en formato .ogg porque ocupa mucho menos espacio que mp3 por ejemplo).
Situarse en el package explorer sobre assets y pulsar F5
Crear la variables de clase:
private Music music;
Implementar el método loadMusic:

private void loadMusic() {
MusicFactory.setAssetBasePath("mfx/");
try {
this.music = MusicFactory.createMusicFromAsset(getEngine().getMusicManager(), this, "pantera_rosa.ogg");
this.music.setLooping(true);
} catch (IOException e) {
Log.e(tag, "loadMusic() " + e.getMessage());
}
}






miércoles, 16 de enero de 2013

Ciclo de vida de una Activity en AndEngine

Una Activity que utilice el motor AndEngine derivará normalmente de la clase BaseGameActivity (o de otra clase de AndEngine). Por el hecho de derivar de esta clase, la Activity tiene un ciclo de vida que se describe en este artículo. El ciclo de vida incluye las necesidades típicas de la inicialización de un juego: crear el motor y configurarlo, cargar los recursos (imágenes, sonidos, fuentes), crear y rellenar la escena.

Este ciclo de vida nos obliga a implementar cuatro métodos que se invocan en el siguiente orden:

  1. onCreateEngineOptions()
  2. onCreateResources()
  3. onCreateScene()
  4. onPopulateScene()
Además de estos cuatro métodos, se pueden implementar otros métodos de AndEngine, pero no es obligatorio.

onCreateEngineOptions() : en este método se crea el objeto Camera que utilizará el motor para visualizar y el objeto EngineOptions. El objeto EngineOptions son las opciones que se aplicarán al objeto Engine que va a controlar el juego. Estas opciones incluyen (entre otras) activar/desactivar música y sonidos, opciones multitouch, opciones de rendering, modo de orientación de la pantalla, modo de resolución de la pantalla, etc.
onCreateResources() : en este método se cargan y se crean los recursos que necesita la Activity. Sonidos, texturas (imágenes), música, fuentes. Dentro de este método, es obligatorio invocar a pOnCreateResourcesCallback.onCreateResourcesFinished() para comunicar a AndEngine que hemos terminado de cargar los recursos.
onCreateScene() : en este método se crea el objeto Scene vacío. Además, en este método se configuran los listeners y handlers de Scene. Este método también debería configurar, si es necesario, los eventos y listeners relacionados con la escena. Cuando se ha configurado el objeto Scene, es obligatorio invocar a pOnCreateSceneCallback.onCreateSceneFinished(scene).
onPopulateScene() : en este método se añaden las entidades hijas a la Scene. Este método se introdujo para separar la creación de la escena de su rellenado con entidades. Como en los dos métodos anteriores, es obligatorio invocar a pOnPopulateSceneCallback.onPopulateSceneFinished() cuando se hayan añadido los hijos.

Ejemplo código completo:

package com.joseanquiles.testandengine;

import java.io.IOException;

import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.WakeLockOptions;
import org.andengine.engine.options.resolutionpolicy.FillResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.ui.activity.BaseGameActivity;

public class MainActivity extends BaseGameActivity {

private static final int WIDTH = 800;
private static final int HEIGHT = 480;
private Scene mScene;
private Camera mCamera;
public EngineOptions onCreateEngineOptions() {
mCamera = new Camera(0,0,WIDTH,HEIGHT);
EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new FillResolutionPolicy(), mCamera);
engineOptions.setWakeLockOptions(WakeLockOptions.SCREEN_ON);
return engineOptions;
}

public void onCreateResources(
OnCreateResourcesCallback pOnCreateResourcesCallback)
throws IOException {
pOnCreateResourcesCallback.onCreateResourcesFinished();
}

public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
throws IOException {
mScene = new Scene();
mScene.setBackground(new Background(0.09804f, 0.6274f, 0));
pOnCreateSceneCallback.onCreateSceneFinished(mScene);
}

public void onPopulateScene(Scene pScene,
OnPopulateSceneCallback pOnPopulateSceneCallback)
throws IOException {
pOnPopulateSceneCallback.onPopulateSceneFinished();
}

}







martes, 15 de enero de 2013

Conceptos en AndEngine

BaseGameActivity

Es una clase derivada de la Activity de Android y que tiene un engine. Es la vista donde se va a dibujar el juego.

LayoutGameActivity

Es otra clase derivada de la Activity de Android. Se utiliza para definir layouts con objetos de IU tales como botones, textfields, etc. Recordemos que un juego puede tener también otras pantallas además de la pantalla propia del juego. También se utiliza esta clase para insertar anuncios de Google.

Engine

El engine es el motor que hace que el juego se ejecute en pequeños pasos (en el tiempo). Se encarga de ir dibujando en pantalla (según los fps) y de actualizar los objetos de la escena

ResolutionPolicy

Es un parámetro del engine. Le indica a AndEngine cómo debe tratar con diferentes tamaños y resoluciones de pantallas. Por ejemplo, RatioResolutionPolicy maximizará el tamaño a lo máximo que permita la pantalla, manteniendo una relación de aspecto concreta. FillResolutionPolicy ocupará toda la pantalla, pero puede distorsionar, ya que no mantendrá la relación de aspecto. Gracias al ResolutionPolicy el programador se olvida de la resolución del terminal. Se hace el programa para una resolución concreta y AndEngine se encarga de dibujar en la resolución del terminal.

Camera

Define el rectángulo de la escena que se dibuja en la pantalla, que no tiene por qué ser la escena completa. Lo normal es tener una Camera por cada Scene. Existen objetos derivados de Camera que permiten hacer zoom y moverse suavemente.

Scene

Es el contenedor de todos los objetos que se dibujan en la pantalla. Una Scene puede tener capas, las cuales pueden contener entidades (estáticas o dinámicas).

Entity

Es un objeto que puede dibujarse, como por ejemplo, sprites, rectángulos, texto, líneas, etc. Una Entity tiene una posición, una rotación, escala, color, etc.

Texture

Una textura es como un canvas gigante donde se pueden situar imágenes más pequeñas, llamadas TextureRegion (en versiones anteriores de AndEngine, el ancho y alto de una textura tenía que ser potencia de 2, pero esa limitación ya no existe). Se pueden situar TextureRegions en cualquier lugar de la textura y extraerlas después a partir de cualquier posición.
En teoría se pueden poner TextureRegions una junto a otra, aprovechando así el espacio al máximo. Sin embargo se recomienda dejar un pixel vacío entre TextureRegions porque en algunos casos se aprecian bordes raros en las imágenes.

TextureRegion

Define un rectángulo en una textura. Los objetos TextureRegion se utilizan en los sprites para manejar imágenes que contienen otras imágenes más pequeñas y que se visualiza una única de ellas en un momento determinado.

Cuestiones importantes

¿Por qué utilizar Textures y TextureRegions? Sería mucho más sencillo tener cada bitmap por separado. La respuesta es por un tema de rendimiento. OpenGL sólo puede tener una textura cargada en memoria en cada momento. Así, si ponemos las imágenes en distintas texturas, OpenGL tendrá que descargar y cargar continuamente de memoria. Sin embargo, teniendo todas las imágenes en una textura, OpenGL sólo tiene que visualizar una parte de esa textura, pero sin cargar otra.
¿Qué tamaña de textura es el máximo? OpenGL soporta texturas de hasta 2048 x 2048. Sin embargo, en algunos terminales, el límite está en 1024 x 1024, así que no se recomienda superar este último tamaño.

AndEngine: Instalación y creación de proyectos

AndEngine es una librería para el desarrollo de juegos para Android. Se trata de un motor OpenGL gratuito desarrollado por Nicolas Gramlich.
Es una plataforma muy potente, pero tiene el inconveniente de que no tiene prácticamente ninguna documentación, y esto hace que mucha gente la abandone a los pocos minutos de empezar. De hecho, es bastante complejo instalarla y empezar un proyecto desde cero.
En este artículo voy a intentar solventar esta dificultad de dar el primer paso con AndEngine, ya que estoy convencido que dar los demás pasos (o sea, desarrollar el juego en sí) ya no es tan complicado.

NOTA: Se explica aquí cómo poner en marcha AndEngine versión GLES2, o sea, la última versión. Nicolas Gramlich abandonó la versión GLES1 hace unos meses y sólo se está evolucionando la versión 2. Todo lo que se explica en este artículo NO es válido para GLES1.

1.Instalación de AndEngine

Requisitos previos:
  • Eclipse
  • Java JDK (mínimo 5)
  • Android SDK (al menos Android 4.0)
  • Plugin ADT para Eclipse
Existe una opción muy sencilla que es descargar e instalar ADT bundle (Android Development Tools) que contiene todo lo necesario (excepto el JDK). Lo tenemos en la siguiente URL de descarga:

http://developer.android.com/sdk/index.html#download

Descargamos el bundle y lo descomprimimos en cualquier directorio del disco duro.

Después vamos a la URL: https://github.com/RealMayo que contiene la versión estable de AndEngine.
Pulsamos sobre la pestaña "Repositories".
Hay que descargar todos los repositorios que aparecen en esta página.
Para ello, pulsamos sobre el primer repositorio. Pulsamos en el botón "ZIP" y descargamos el repositorio.
Volvemos a la página anterior y vamos descargando todos los repositorios.

Descomprimimos todos los ficheros ZIP descargados en el disco duro.

El siguiente paso es abrir Eclipse (que viene con el adt-bundle).

File > Import... > General > Existing Projects into Workspace
Next
Select root directory: elegir el directorio base donde se han instalado todos los repositorios
Finish
Aparecerá un error como este: Unable to resolve target 'android-15'
Para resolver este problema:

Window > Android SDK Manager

Seleccionar los siguientes elementos (algunos ya estarán instalados y no hay que seleccionarlos):

API 17: SDK Platform, ARM EABI v7a System Image, Google APIs

API 16: SDK Platform, ARM EABI v7a System Image, Intel x86 Atom System Image, Google APIs
API 15: SDK Platform, ARM EABI v7a System Image, Intel x86 Atom System Image, Google APIs
API 14: SDK Platform, ARM EABI v7a System Image, Google APIs
API 8: SDK Platform, Google APIs
API 7: SDK Platform, Google APIs

Volver a Eclipse.

Seleccionar con el botón derecho cada uno de los proyectos de AndEngine > Properties > Java Compiler
Marcar: Enable project specific settings
Compiler compliance level: 1.6

Ahora aparecerán otros errores en la pestaña "Problems" de Eclipse.
Hay que entrar en cada uno de los proyectos (excepto el proyecto AndEngine) y hacer lo siguiente:

Proyecto > Properties > Android
En las librerías, aparecerán algunas con una X roja. Hay que seleccionarlas, borrarlas con el botón "Remove", y luego añadir la misma con el botón "Add".

Salir de Eclipse y volver a entrar. Se recompilará todo.
Ya no debería salir ningún error.


2.Aplicación


Abrir Eclipse

File > New > Android Application Project

    Minimum required SDK = 2.2
    Target SDK = 16
    NO create custom launcher icon

Next

Create blank activity

Next

Finish

Package Explorer > proyecto > Android Tools Fix Project Properties

Package Explorer > proyecto > Properties > Java compiler >>> 1.6

Package Explorer > proyecto > Android

    Library
    Add
         AndEngine

OK

Abrir MainActivity.java

Vaciar la clase

Heredar de BaseGameActivity

Implementar los métodos:

    onCreateEngineOptions()
    onCreateResources()
    onCreateScene()
    onPopulateScene()

3. Publicación en el Market

Si se desea la aplicación en el Market de Android hay que realizar unos pocos pasos más:

Copiar el fichero andengine.jar al folder libs del proyecto. El fichero andengine.jar se encuentra en el directorio bin del proyecto AndEngine.

Proyecto > Properties > Android > Eliminar todas las librerías (AndEngine)

Project > Clean...

Project > Android Tools > Fix Project Properties

Y ahora ya se puede exportar la aplicación para el market.