Anda di halaman 1dari 11

Clase 2 Arquitectura de la aplicacin

Clase 2
Arquitectura de la aplicacin

Autor: Ernesto Gigliotti

Este obra est bajo una Licencia Creative Commons Atribucin-CompartirIgual 4.0 Internacional.
UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


ndice

Creando el administrador de recursos.

Creando el administrador de escenas.

Manejando ms de una escena: el splash.

Uso del timer provisto por el engine

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Creando el administrador de recursos
Modificaremos nuestra aplicacin para no generar en GameScene toda la carga de recursos
(imgenes y texturas), sino que escribiremos una clase llamada ResourcesManager que se
encargar de estas tareas, ejecutando la carga y liberacin de recursos cuando la escena
aparece y desaparece, aprovechando al mximo los lmites de memoria que posee el
dispositivo donde se ejecuta el juego.
Creamos la clase ResourcesManager y creamos un singleton para la misma:
public class ResourcesManager {
private static ResourcesManager instance;
private ResourcesManager() {
}
public static ResourcesManager getInstance() {
if(instance==null)
instance = new ResourcesManager();
return instance;
}
Como se observa en el cdigo, el constructor de esta clase es privado, de modo que no se
puede crear un objeto de dicha clase, sino que debemos obtener la instancia mediante el
mtodo esttico getInstance. De este modo nos aseguramos que solo existir un objeto
ResourcesManager en nuestra aplicacin, y brindamos la facilidad de adquirir dicho objeto
desde cualquier scope, ya que utilizaremos un mtodo esttico.
A continuacin, definiremos algunos atributos que sern de utilidad para cargar los recursos:
public Engine engine;
public Camera camera;
public BaseGameActivity gameActivity;
Ahora escribimos un mtodo esttico que llamaremos en nuestra Activity, inicializando estos
atributos.
public static void prepareResourcesManager(BaseGameActivity gameActivity,
Camera camera)
{
ResourcesManager rm = getInstance();
rm.camera = camera;
rm.gameActivity = gameActivity;
rm.engine = gameActivity.getEngine();
}
De modo que en nuestra Activity, en el mtodo onCreateResources, ahora llamamos a
prepareResources
@Override
public void onCreateResources(OnCreateResourcesCallback
pOnCreateResourcesCallback) {
ResourcesManager.prepareResourcesManager(this,camera);
pOnCreateResourcesCallback.onCreateResourcesFinished();
}

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Escribiremos dos mtodos, uno para cargar y otro para liberar los recursos de la pantalla del
juego.
Comenzaremos escribiendo loadGameResources, en donde colocaremos el cdigo que antes
estaba en la clase GameScene:
public void loadGameResources()
{
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
logoTextureAtlas = new BuildableBitmapTextureAtlas(
gameActivity.getTextureManager(),
70, 70, TextureOptions.BILINEAR);
logoRegion =
BitmapTextureAtlasTextureRegionFactory.createFromAsset(
logoTextureAtlas,
gameActivity,
"logo.png");
try
{
logoTextureAtlas.build(new BlackPawnTextureAtlasBuilder
<IBitmapTextureAtlasSource, BitmapTextureAtlas>(0, 1, 0));
logoTextureAtlas.load();
}
catch (TextureAtlasBuilderException e)
{
Debug.e(e);
}
}
Ahora escribimos el mtodo unloadGameResources:
public void unloadGameResources()
{
logoTextureAtlas.unload();
logoTextureAtlas = null;
logoRegion = null;
}
Como se observa, hay dos atributos que debemos definir en la clase:
private ITextureRegion logoRegion;
private BuildableBitmapTextureAtlas logoTextureAtlas;
Para obtener la regin del logo desde fuera de esta clase, escribimos el mtodo
getLogoRegion:
public ITextureRegion getLogoRegion() {
return logoRegion;
}

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Ahora estamos en condiciones de usar la clase ResourcesManager en el mtodo populateScene
de la clase GameScene, donde antes creabamos el Sprite, ahora colocamos:
ResourcesManager rm = ResourcesManager.getInstance();
rm.loadGameResources();
Sprite logoSprite = new Sprite(100, 240, rm.getLogoRegion(),
mEngine.getVertexBufferObjectManager());

Bajar Ejemplo3: http://www.lslutnfra.com/androidJuegos

Creando el administrador de escenas


De la misma forma que creamos una clase que se encargar de cargar y liberar todos los
recursos, en esta oportunidad escribiremos una clase encargada de manejar las escenas de
nuestro juego. Por el momento, solo contamos con la escena del juego, pero luego seguiremos
agregando escenas (splash, menu, pantalla de carga, etc.) y todas sern administradas por
esta clase.
public class SceneManager {
private static SceneManager instance;
private SceneManager() {
}
public static SceneManager getInstance()
{
if(instance==null)
instance = new SceneManager();
return instance;
}
Al igual que en la clase ResourcesManager, creamos el mtodo getInstance para obtener un
singleton del tipo SceneManager.
Definiremos el atributo private currentScene, en donde almacenaremos una referencia del
objeto Scene que actualmente esta cargado en pantalla:
private Scene currentScene;
Luego escribimos el mtodo setScene, que recibe un objeto Scene y se lo asigna al objeto
Engine, permitiendo de esta forma que se represente en pantalla, tambin se guardar en el
atributo currentScene el objeto seteado en el Engine:
public void setScene(Scene scene)
{
currentScene = scene;
ResourcesManager.getInstance().engine.setScene(scene);
}

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Escribimos a continuacin el mtodo getCurrentScene, que nos devolver el objeto Scene que
se encuentra cargado actualmente en pantalla:
public Scene getCurrentScene()
{
return currentScene;
}
Ahora estamos encondiciones de crear el mtodo que cree nuestro objeto GameScene,
cargando previamente los recursos necesarios. Comenzaremos por definir un atributo que
corresponda al GameScene:
private GameScene gameScene;
Una vez definido este atributo, escribimos el mtodo createGameScene:
public void createGameScene() {
ResourcesManager rm = ResourcesManager.getInstance();
rm.loadGameResources();
gameScene = new GameScene(rm.engine,rm.gameActivity);
gameScene.createGameScene();
setScene(gameScene);
}
Como se observa, este mtodo llama a loadGameResources de la clase ResourcesManager, el
cual se encargaba de cargar todas las texturas que se utilizaran en el juego. Tambin utiliza el
mtodo creado previamente en esta misma clase, setScene para cargar la escena en pantalla.
No debemos olvidar quitar la llamada a loadGameResources que qued en GameScene.
Por ltimo, escribimos el mtodo disposeGameScene, el cual liberar los recursos cargados en
createGameScene:
public void disposeGameScene() {
ResourcesManager.getInstance().unloadGameResources();
}
Para utilizar SceneManager, deberemos cambiar los mtodos onCreateScene y
onPopulateScene en nuestra Activity. Comenzaremos por el primer mtodo:
@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)

SceneManager.getInstance().createGameScene();
GameScene gameScene = (GameScene)
SceneManager.getInstance().getCurrentScene();
pOnCreateSceneCallback.onCreateSceneFinished(gameScene);
}
Puede observarse la utilizacin del mtodo createGameScene del objeto singleton obtenido
mediante getInstance del tipo SceneManager. Luego se obtiene una referencia del objeto
GameScene creado, pidindole al SceneManager la escena actual.

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Realizamos un reemplazo similar en el metodo onPopulateScene:
@Override
public void onPopulateScene(Scene pScene,OnPopulateSceneCallback
pOnPopulateSceneCallback) {
GameScene gameScene = (GameScene)
SceneManager.getInstance().getCurrentScene();
gameScene.populateScene();
}

pOnPopulateSceneCallback.onPopulateSceneFinished();

Bajar Ejemplo4: http://www.lslutnfra.com/androidJuegos

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Manejando ms de una escena: el splash
Como es comn en la mayoria de los juegos, requerimos de una pantalla de splash al iniciar,
de modo que incorporaremos una nueva escena que ser administrada por la clase
SceneManager para ser disparada a voluntad.
Cargando nuevos recursos para el splash
Comenzaremos la tarea de agregar una escena, agregando los recursos que sta requiere,
para ello, modificaremos la clase ResourcesManager y agregaremos los siguientes atributos:
private Font splashFont;
private ITexture splashFontTexture;
El primero es un objeto Font, el cual es requerido por el objeto Text que utilizaremos en la
escena para representar un texto en pantalla. El segundo es la textura donde cargaremos el
archivo de fuente (archivo ttf)
Escribiremos a continuacin el mtodo loadSplashResources el cual crear los dos objetos
mencionados.
public void loadSplashResources()
{
splashFontTexture = new BitmapTextureAtlas(gameActivity.getTextureManager(),
256, 256,
TextureOptions.BILINEAR_PREMULTIPLYALPHA);
FontFactory.setAssetBasePath("fonts/");
splashFont = FontFactory.createStrokeFromAsset(
gameActivity.getFontManager(),
splashFontTexture,
gameActivity.getAssets(),
"PaladinFLF.ttf", 50f, true, 0xFFFF0000, 1f, 0xFF008080);
}

splashFont.load();

Creamos un BitmapTextureAtlas como lo hicimos anteriormente para el Sprite. En esta


oportunidad, el atlas contendr las imagenes de la fuente. No es fcil determinar el tamao
requerido por el atlas, ya que depender del tamao y tipo de fuente. Se recomienda
comenzar con 256x256 e ir ajustando estos valores al mnimo posible.
Luego configuramos el path raz donde la clase FontFactory buscar los archivos de fuentes,
mediante el metodo esttico setAssetBasePath. Deberemos colocar el archivo de fuente all.

Creamos un objeto Font mediante el mtodo esttico createStrokeFromAsset, el cual recibe el


nombre de la fuente, el tamao, el color de relleno, el ancho de la lnea de contorno y el color
de la lnea.
Por ltimo cargamos la fuente en el atlas mediante el mtodo load.

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Escribimos el mtodo unloadSplashReources que utilizaremos al dejar de mostrar el splash:
public void unloadSplashResources() {
splashFont.unload();
splashFont = null;
splashFontTexture.unload();
splashFontTexture=null;
}
Agregamos el mtodo getSplashFont que nos permitir usar la fuente desde otra clase:
public Font getSplashFont() {
return splashFont;
}
Crearemos una escena para el splash, escribiendo la clase SplashScene que herede de Scene:
public class SplashScene extends Scene {
public void createSplashScene()
{
ResourcesManager rm = ResourcesManager.getInstance();
setBackground(new Background(Color.WHITE));
Text text = new Text(400,240,rm.getSplashFont(),"Mi Juego",
rm.engine.getVertexBufferObjectManager());
attachChild(text);

}
}
Como se observa, escribimos en nuestra clase SplashScene, que hereda de Scene, el mtodo
createSplashScene, en el cual cargamos un color de fondo en blanco, y creamos un objeto
Text, el cual recibe en su constructor, la posicin (400;240 es el centro de la pantalla), el
objeto Font, el texto a mostrar, y el objeto VertexBufferObjectManager obtenido desde el
objeto Engine. Por ltimo agregamos el objeto Text a la escena mediante attachChild.
Agregamos el manejo de esta escena a la clase SceneManager, comenzando por agregar el
atributo SplashScene:
private SplashScene splashScene;
Luego escribimos los mtodos create y dispose al igual que para la escena del juego:
public void createSplashScene()
{
ResourcesManager rm = ResourcesManager.getInstance();
rm.loadSplashResources();
splashScene = new SplashScene();
splashScene.createSplashScene();
setScene(splashScene);
}

public void disposeSplashScene()


{
ResourcesManager.getInstance().unloadSplashResources();
}
Ya estamos en condiciones de modificar la inicializacin de nuestro juego para que muestre la
escena del splash y luego de un tiempo determinado, se muestre la escena del juego, esto lo
haremos configurando un timer provisto por el engine.
UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

Clase 2 Arquitectura de la aplicacin


Uso del timer provisto por el engine
Modificaremos la Activity, para disparar primero la escena del splash, para ello comenzamos
por modificar el mtodo onCreateScene:
@Override
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)
throws IOException {
SceneManager.getInstance().createSplashScene();
SplashScene splashScene = (SplashScene)
SceneManager.getInstance().getCurrentScene();
pOnCreateSceneCallback.onCreateSceneFinished(splashScene);
}
Ahora en vez de crear el objeto GameScene, creamos el SplashScene. Luego modificaremos el
mtodo onPopulateScene para lanzar un timer y luego de un tiempo, cargamos los recursos del
juego y cargamos la escena de juego:
@Override
public void onPopulateScene(Scene pScene, OnPopulateSceneCallback
pOnPopulateSceneCallback) throws IOException {
Tiempo, 2 seg

ResourcesManager rm = ResourcesManager.getInstance();
rm.engine.registerUpdateHandler(new TimerHandler(2f,new ITimerCallback() {
@Override
public void onTimePassed(TimerHandler pTimerHandler) {
ResourcesManager rm = ResourcesManager.getInstance();
rm.engine.unregisterUpdateHandler(pTimerHandler);
rm.loadGameResources();
SceneManager.getInstance().createGameScene();
SceneManager.getInstance().disposeSplashScene();

}
}));
pOnPopulateSceneCallback.onPopulateSceneFinished();

}
Como se observa en el cdigo, obtenemos la instancia de ResourcesManager para obtener el
objeto engine, al que le ejecutamos el mtodo registerUpdateHandler al cual le pasamos una
clase annima que hereda de TimerHander y que recibe como argumento el tiempo en que se
ejecutar el callback asignado al timer, y dicho callback, que es una clase annima que
implementa la interfaz ITimerCallback.
Esta interfaz nos obliga que escribir el mtodo onTimePassed, el cual se ejecutar luego del
tiempo prefijado. Dentro de este mtodo volvemos a obtener la referencia de
ResourcesManager para quitar el registro del timer del engine, mediante
unregisterUpdateHandler.
Posteriormente cargamos los recursos del juego mediante loadGameResources (tener en
cuenta que cuando haya muchos recursos, este mtodo es el que va a demorar, mientras
tanto, el usuario sigue viendo en pantalla la escena del splash) y por ltimo ejecutamos el
mtodo createGameScene para que SceneManager cree la escena del juego y la cargue en el
engine y liberemos los recursos utilizados en el splash mediante disposeSplashScene.

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

10

Clase 2 Arquitectura de la aplicacin


Debido a que ahora cargamos los recursos del juego cuando se ejecuta el callback del timer,
deberemos de dejar de cargarlos dentro de la clase SceneManager:
public void createGameScene() {
ResourcesManager rm = ResourcesManager.getInstance();
//rm.loadGameResources();
gameScene = new GameScene(rm.engine,rm.gameActivity);
gameScene.createGameScene();
Agregamos este mtodo
gameScene.populateScene();
setScene(gameScene);
}
Es conveniente cambiar de lugar la llamada a este mtodo, ya que loadGameResources,
en un futuro, no solo cargar recursos de la escena del juego, sino tambien de las
escenas de men, niveles, y dilogos, y el mtodo createGameScene es propio de la
escena del juego
Al ejecutar nuestro juego, veremos la escena del splash y luego de 2 segundos, veremos la
escena del juego:

Bajar Ejemplo5: http://www.lslutnfra.com/androidJuegos

UTN FRA Desarrollo de juegos en Android http://www.lslutnfra.com

11

Anda mungkin juga menyukai