Clase_2

download Clase_2

of 11

description

Android para juegos

Transcript of Clase_2

  • Clase 2 Arquitectura de la aplicacin

    Clase 2Arquitectura 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 1

  • 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 2

  • 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

    @Overridepublic void onCreateResources(OnCreateResourcesCallback pOnCreateResourcesCallback) {

    ResourcesManager.prepareResourcesManager(this,camera);pOnCreateResourcesCallback.onCreateResourcesFinished();

    }

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

  • 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 (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 4

  • Clase 2 Arquitectura de la aplicacin

    Ahora estamos en condiciones de usar la clase ResourcesManager en el mtodo populateScenede 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 seguiremosagregando 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 5

  • 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:

    @Overridepublic 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 6

  • Clase 2 Arquitectura de la aplicacin

    Realizamos un reemplazo similar en el metodo onPopulateScene:

    @Overridepublic 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 7

  • 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 8

  • 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 9

  • 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:

    @Overridepublic 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 deljuego y cargamos la escena de juego:

    @Overridepublic void onPopulateScene(Scene pScene, OnPopulateSceneCallback pOnPopulateSceneCallback) throws IOException { 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

    Tiempo, 2 seg

  • 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(); 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

    Agregamos este mtodo