VISITAS:

martes, 23 de abril de 2013

Introducción a Struts 2

Struts 2 es un framework para el desarrollo de aplicaciones web basado en:

  • Acciones
  • Interceptores
  • Librería de tags

Acciones

Una acción puede ser cualquier clase Java que cumpla con las condiciones del framework.
Una acción hace tres cosas:
  • Realiza la lógica asociada a una request. Esta lógica se implementa en el método execute() de la acción. Una acción no trata con la request del servlet, ni con la response. Trata con la lógica de negocio.
  • Contiene los datos que vienen de la request y que van al resultado. Estos datos se almacenan como atributos de la acción. Al estar los datos disponibles en la acción, siempre estarán disponibles para la ejecución de la lógica de negocio. La acción simplemente implementa propiedades tipo javabean para cada dato que tiene que transportar. Los parámetros de la request que coinciden con propiedades de la acción se rellenan automáticamente antes de ejecutar la acción. Además, estas propiedades tipo javabean, también estarán disponibles para renderizar el resultado (por ejemplo en la página JSP).
  • Decide cuál es el resultado que se debe visualizar. Cada acción retorna un String que selecciona el resultado que se va a renderizar.

Paquetes de acciones

Los paquetes son contenedores lógicos de acciones.
Un paquete define el namespace (URL base) para todas las acciones de ese paquete y los interceptores que se activarán en todas las acciones del paquete.
Un paquete puede heredar de otro paquete, tomando todas las propiedades del paquete padre, pudiendo añadir nuevas propiedades. Si no heredamos de otro paquete, deberíamos al menos heredar del paquete struts-default, que viene definido en la distribución de struts (fichero struts2-core.jar, struts-default.xml).
Cada paquete define los interceptores y pilas de interceptores que utilizarán las acciones de ese paquete. En caso de herencia, se heredan las pilas e interceptores de la clase padre. Se define una pila de interceptores por defecto, que será la que se ejecute en caso de que la acción no declare otra específicamente.
Normalmente, las acciones se organizan en paquetes por funcionalidad o por nivel de seguridad (por ejemplo un paquete para acciones que requieren autenticación previa y otro paquete para acciones que no requieren autenticación).

Paquete struts-default

Este paquete que viene con la distribución de struts2 (está dentro del fichero struts-core.jar) contiene muchos componentes que se pueden recoger al heredar de este paquete. Es el fichero struts-default.xml
Uno de los componentes más importantes dentro de struts-default es la pila de interceptores por defecto, o defaultStack. Esta pila de interceptores se aplica por defecto a todas las acciones dentro de los paquetes que heredan de struts-default (salvo que se defina otra pila por defecto).
Por ejemplo, la pila por defecto incluye un interceptor llamado params que se encarga de pasar los datos de la request a propiedades de la acción (javabean).
Lo habitual es que todos los paquetes que definamos hereden del paquete struts-default obteniendo así automáticamente las funcionalidades que ofrece este paquete, entre otras, la pila de interceptores por defecto.

Implementar acciones 

Una acción es cualquier clase java que tiene un método execute(). No tiene que heredar de ninguna otra clase ni implementar ningún interfaz. Sin embargo, es útil que las acciones implementen el interfaz Action, ya que entonces tendrán acceso a las constantes definidas en este interfaz. Son constantes para los valores retornados por el método execute: ERROR, SUCCESS, INPUT, LOGIN, NONE. El resultado retornado por la acción determina lo que Struts va a ejecutar la finalizar la acción. Si retorna SUCCESS, el framework dirige a la página definida como SUCCESS para la acción. Si retorna ERROR, el framework dirige a la página definida como ERROR para la acción.
Si deseamos obtener algo más de funcionalidad, podemos heredar nuestra acción de la clase ActionSupport, la cual implementa el interfaz Action. Pero además, implementa otros interfaces muy útiles para internacionalización y validación, proporcionando una implementación por defecto muy útil. Veamos a continuación estas dos importantes funcionalidades: validación e internacionalización.

Validación básica

La clase ActionSupport proporciona una validación básica que será suficiente en muchos casos. El requisito para poder utilizar esta funcionalidad de validación básica es heredar nuestro paquete del paquete struts-default y que nuestra clase acción herede de la clase ActionSupport.
La pila de interceptores por defecto (defaultStack) introduce un interceptor denominado workflow, de la clase Java DefaultWorkflowInterceptor. Este interceptor desvía el flujo a la página de entrada (página llamante) si ocurre un error en la validación. Este interceptor se ejecuta después que el interceptor params, o sea, cuando los datos ya están metidos en los atributos de la acción.
Veamos cómo se ejecuta el interceptor workflow. Cuando se dispara este interceptor, busca un método validate() en la acción. Este método puede chequear los atributos de la acción y detectar errores en los valores pasados como parámetros. Cada vez que ocurre un error de validación, se añade este error a una lista utilizando el método AddFieldError() que proporciona ActionSupport. Después de ejecutarse el método validate() de la acción, el control vuelve al interceptor workflow, el cual mira si se ha generado algún error. Si hubiera algún error, este interceptor altera el flujo de la request y devuelve el control a la página de entrada, mostrando el error junto al campo o campos que han provocado el error.
El método validate() tiene dos opciones para generar errores:
  • addFieldError(fieldName, errorMessage) : genera un error de validación asociado a un campo de entrada
  • addActionError(errorMessage) : genera un error de validación a nivel de acción
Como se puede ver hasta ahora, la filosofía de struts es dejar toda la lógica de negocio en el método execute() de la acción. Todo lo demás, validaciones, paso de parámetros, etc. queda fuera de este método.

Internacionalización

La clase ActionSupport proporciona también una implementación para el manejo de la internacionalización, es decir, gestiona los ficheros de mensajes en varios idiomas. Tenemos a nuestra disposición el método getText() de la clase ActionSupport para obtener mensajes a partir de un clave. Estos mensajes están en un fichero asociado a la acción y se recuperan a partir de una clave. El fichero de mensajes tiene el mismo nombre que la clase que implementa la acción y tiene que estar en el mismo paquete java. Este fichero es un fichero de properties normal de java.
Para definir ficheros de mensajes en varios idiomas, añadiremos a cada uno en el nombre el sufijo con el idioma correspondiente: XXX_es.properties.

Transferencia de datos a la acción

Hasta ahora hemos visto que los datos que  vienen en la request se pueden transferir a atributos de la clase acción. Esos datos son simples. Por ejemplo, si en la request va un atributo que se llama "nombre", el interceptor param intentará transferirlo al atributo "nombre" de la acción, a través de los métodos setNombre() y getNombre().





lunes, 4 de marzo de 2013

Cambiar el tono de una canción MP3

El problema

Muchas veces tenemos canciones en MP3 que no están en la tonalidad que nos gustaría.
¿Por qué? Normalmente porque queremos acompañarlas con algún instrumento, por ejemplo, la guitarra o el bajo. A estas pistas se le llama a veces "back track", refiriéndose a pistas de fondo que acompañan nuestro instrumento, para que éste no suene solo.
La solución típica es adaptar nuestro instrumento y nuestro acompañamiento a la tonalidad en que tenemos el MP3. Pero esto supone cambiar nuestras partituras (o tablas de acordes) y lo que es peor, al ensayar en otra tonalidad de la que luego vamos a interpretar, no nos sirve de mucho como práctica.
Pongamos un ejemplo: tenemos que interpretar la canción en DO mayor, sin embargo tenemos un MP3 de la canción en FA mayor. La opción que tenemos es cambiar nuestras partituras a FA mayor y acompañar así el MP3. Pero como hemos dicho, no nos vale de mucho tocar la canción en FA mayor si luego vamos a tocarla en DO mayor ¿verdad? Aparte de tener que reescribir todas las partituras en FA mayor.
Existe otra solución mucho más cómoda...

Cambiar el tono del MP3

Si no nos convence la solución anterior, tenemos otra, que aunque tiene alguna pega que luego comentaremos, cumple perfectamente su función, sobre todo para ensayo y preparación.
Esta solución consiste en cambiar la tonalidad del MP3.

Llevo varios meses buscando cómo cambiar el tono de un MP3 y no lo encontraba. He leído artículos sobre cómo hacer un paso al dominio de la frecuencia, trasponer y luego volver al dominio del tiempo. La idea es interesante, pero no quería ponerme a implementarla, porque me llevaría bastante tiempo. Así que me decidí a investigar los programas de procesamiento de audio que existen, sobre todo los gratuitos.
Al final dí con la solución: Audacity.
Audacity es un programa gratuito que se puede descargar bien en la versión portable (es la que yo prefiero), o en la versión instalable:


Una vez instalado el programa, lo arrancamos y cargamos el MP3 que queremos cambiarle el tono. Para ello vamos al menú File - Open, o bien,si se ha instalado en español, Archivo - Abrir. Buscamos en el disco duro el fichero MP3 que queremos transponer.

En primer lugar debemos detectar en qué tonalidad está el MP3 original.
Hay varias formas de saberlo. Quizás la más práctica, aunque no la más rápida, es reproducir la canción y con un teclado intentar pillar la tonalidad. Si tenemos la partitura de la canción es relativamente sencillo, ya que haciendo uso de un teclado, vamos intentando "pillar" las notas en el MP3 y luego comparamos con nuestra partitura para ver la diferencia de tonalidad.
Si sólo tenemos los acordes, es un poco más complicado, pero también se puede hacer. Buscamos el acorde principal e intentamos casarlo con la canción, subiendo o bajando de acorde. Por ejemplo, si en nuestra partitura tenemos la canción en DO mayor, reproduciremos el MP3 y probamos si el DO mayor encaja (normalmente no, porque en caso afirmativo, ya hemos acabado). Seguimos probando subiendo a RE mayor, MI mayor, DO# mayor, etc. Y luego vamos bajando: SI mayor, LA mayor etc. Cuando hayamos localizado la tonalidad principal, ya sabemos el tono de la canción MP3. Y por tanto, ya sabemos cuántos tonos tenemos que subir o bajar para conseguir el MP3 en el tono que queremos.

Otra opción sería utilizar algún programa que detecte el tono de una canción, pero eso lo considero mucho menos fiable. A mí por lo menos nunca me funcionan bien...

Después vamos al menú Effect - Change Pitch, o bien, Efecto - Cambiar tono.
En esta ventana le tenemos que decir cuántos semitonos queremos subir o bajar. Aplicamos el cambio y ya tenemos la canción en la tonalidad deseada.

Ahora sólo tenemos que exportar la canción a MP3 con File - Export o bien Archivo - Exportar.

Problemas de esta solución

En mi opinión, la solución que propongo tiene dos problemas:

  1. Encontrar la tonalidad del MP3 puede ser un poco complicado, pero es cuestión de práctica. Al final lo encuentras.
  2. El MP3 resultante no es perfecto, o sea, no suena como el original, sobre todo la voz humana. Sin embargo, mi opinión es que es perfectamente válido para ensayar, y para eso lo utilizo yo. No se te ocurra enviárselo a un amigo para que escuche una canción, ya que no le va a gustar mucho.





martes, 19 de febrero de 2013

Juego para Android: Retro Kong Jungle

El juego

Si tienes más de 30 años seguramente has conocido y has jugado con aquellas antiguas consolas "monojuego" que nos hacían pasar ratos extraordinarios.
Comparado con lo que tenemos ahora, se podría decir que: eran muy caras para lo que ofrecían (un solo juego), la calidad gráfica del juego era un poco pobre (habitualmente blanco y negro y muy poca resolución), no tenían muchas variantes (el juego siempre era lo mismo, aunque cada vez más difícil por la velocidad).
Sin embargo: eran juegos muy adictivos, nos hacían pasar horas maravillosas, habitualmente desarrollaban el sentido del ritmo en el jugador. Y muchas otras cosas buenas. Pero sobre todo: era lo que había en aquéllos tiempos (años 80).
Supongo que ya sabes a qué consolas me refiero. Aquí tienes algún ejemplo:

http://blog-mundoretro.blogspot.com.es/2012/04/game-watch-las-maquinitas-de-nintendo.html

Estas consolas son muy difíciles de conseguir hoy en día y además son muy caras (en caso de encontrarlas de segunda mano). Así que he decidido, junto a mis hijas Cristina y Patricia, hacer uno de estos juegos para Android.
Dicho y hecho. Utilizando AndEngine me puse a ello y en un par de días he conseguido algo que se parece bastante a uno de aquellos juegos:

https://play.google.com/store/apps/details?id=com.joseanquiles.android.retrokongjungle



Es un juego muy divertido que ya ha conseguido que mis hijas no puedan despegarse del móvil, intentando continuamente batir el record (actualmente lo tiene Patricia con 2800 puntos). Por supuesto, es un juego gratuito y sin publicidad de ningún tipo, para que pueda jugar el máximo número de video-juego-adictos y otros que simplemente quieren pasar un buen rato recordando viejos tiempos.
¡Qué lo disfrutéis!

La historia

La idea del juego es muy sencilla.
Se trata de King Kong y "la chica".
La chica se quiere bañar plácidamente bajo las cataratas del Niágara. Pero la cosa no es tan fácil como ella pensaba. Por la caída de agua caen troncos de madera de vez en cuando con el consiguiente riesgo de aplastarla. Además, por el río bajo la cascada circulan serpientes venenosas que van directamente a picarle.
Pero el galante King Kong no está dispuesto a que la chica muera, así que recogerá todos los troncos que caen por la cascada antes de aplastar a la chica, y pisará a cualquier serpiente que se acerque a ella.
Al principio, la tarea de King Kong es sencilla, porque los troncos caen muy despacio y las serpientes se acercan poco a poco a la chica. King Kong no tendrá problemas en los inicios del juego.
Sin embargo, conforme avanza el juego, la velocidad se incrementa y King Kong tendrá que ser muy rápido para poder parar todos los troncos y serpientes que se acercan a la chica.

Cómo se juega

Jugar a Retro Kong Jungle es muy sencillo.
Abajo tenemos dos botones (los de arriba sirven para ver los créditos y para resetear el juego y volver a empezar). Esos dos botones de abajo sirven para que King Kong vaya de un lado a otro de la cascada.
En el lado izquierdo puede coger troncos. Y en el lado derecho puede pisar serpientes.
Hay que estar muy atentos para estar en el momento adecuado y poder coger el tronco antes de que aplaste a la chica. Para ello, llevaremos a King Kong hacia la derecha, y cuando el tronco esté junto a la poderosa mano de King Kong, entonces volvemos a pulsar el botón derecho y cogeremos el tronco.
Igualmente, cuando una serpiente se acerque a la chica, tendremos que estar en el lado izquierdo y pulsar el botón izquierdo justo cuando la serpiente pase por debajo de los pies de King Kong.
¿Fácil? Sí, pero cuidado. Los troncos y las serpientes se van intercalando y tendremos que ir llevando a King Kong de un lado para otro, cogiendo troncos y pisando serpientes.
Cuando aumenta la velocidad podrás disfrutar de unos momentos realmente emocionantes.
Además, cada 250 puntos, la chica dará una recompensa sorpresa a King Kong.



lunes, 11 de febrero de 2013

Crear imagen del sistema con Windows 7

Introducción

Crear una imagen del disco es un proceso bastante sencillo de llevar a cabo y que puede resultar de mucha utilidad en el futuro.
Normalmente se recomienda hacer una imagen del disco tras instalar el sistema operativo y después de instalar los programas que utilizamos habitualmente. Pero yo recomiendo hacer la imagen de disco un poco antes, justo después de instalar el sistema operativo, actualizar todos los service packs, instalar todos los drivers de nuestro equipo, y quizás, algún programa muy básico pero que utilizamos muy frecuentemente.
¿Por qué? Por varias razones, pero una sobre todo: porque las aplicaciones se actualizan con frecuencia, entonces, cuando queramos recuperar, no nos valdrá de mucho tener una imagen de hace un año con las versiones de las aplicaciones hace un año. Además, instalar las aplicaciones no suele llevar mucho tiempo.
Pues dicho esto, voy a intentar explicar cómo hacer una imagen de nuestro disco en Windows 7 y luego cómo recuperarla en caso de fallo.

Crear una imagen

En primer lugar, introducimos un DVD-RW vacío en la unidad de DVD.
Abrimos el panel de control (Inicio > Panel de control)
Pulsamos en la sección "Sistema y Seguridad"
En la sección "Copias de seguridad y restauración", en el frame izquierdo de esta ventana, pulsamos sobre "Crear imagen de sistema".
Aparecerá una nueva ventana titulada "¿Dónde desea guardar la copia de seguridad?". Seleccionar la opción "En uno o más DVDs" y en el combobox, seleccionar la unidad de DVD donde hemos introducido el disco. Pulsar "Siguiente"
En la siguiente ventana se nos mostrará las unidades que componen el sistema. Pulsar "Siguiente".
En la siguiente ventana, pulsar en "Iniciar copia de seguridad".
A partir de aquí, nos irá pidiendo discos para la copia. Es conveniente etiquetarlos indicando al menos, un identificador del PC que estamos haciendo la imagen, versión de Windows, la fecha de hoy, y el número de disco.

Para poder recuperar esa imagen en caso de que Windows se dañara, tenemos que crear antes un disco de recuperación desde el que podamos arrancar Windows. Esto lo vemos en el siguiente apartado.

Crear un disco de recuperación

En primer lugar, introducimos un DVD-RW en la unidad de DVD.
Abrimos el panel de control (Inicio > Panel de control)
Pulsamos en la sección "Sistema y Seguridad"
En la sección "Copias de seguridad y restauración", en el frame izquierdo de esta ventana, pulsamos sobre "Crear un disco de reparación del sistema".
A continuación se formatea el disco y se escribe el disco de arranque.

Recuperar una imagen del sistema

Cuando Windows se daña y queremos sustituirlo por la imagen del sistema que hemos creado, tenemos que arrancar con el disco de reparación.
Para ello, tenemos que entrar en la configuración de la BIOS y poner como primer disco de arranque el DVD. Esto depende de cada ordenador y por tanto no se va a explicar aquí.

Cuando se arranca con el disco de reparación hay que seleccionar la opción de restaurar la computadora con una imagen del sistema que se ha creado anteriormente. Entonces hay que ir introduciendo los discos con la imagen del sistema.






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

}