sábado, 5 de mayo de 2012

¡OpenGL en Android para todos!


En este primer post vamos a aprender a manejar los conceptos básicos de una de las librerías graficas más utilizadas, OpenGL.
Luego iremos haciendo cosas un poco más complejas, hasta llegar a gráficos en 3D y sus respectivas operaciones, pero primero lo primero.
Lo primero que debes conocer antes de empezar a graficar con OpenGL, son las clases a utilizar, y son:
-          GLSurfaceView, la clase que te permite escribir las aplicaciones con OpenGL
-          GLSurfaceView.Renderer, es una interfaz de renderizado genérica donde escribirás el código de lo que quieras que se dibuje.

PARA ENTENDER MÁS RÁPIDO…
Para que puedas asimilar la forma de graficar en OpenGL rápidamente, puedes hacer una pequeña analogía con un pintor y un lienzo, en este caso el pintor sería la interfazGLSurfaceView.Renderer y el lienzo sería GLSurfaceView. Por lo dicho anteriormente, elGLSurfaceView sería el parámetro que pasaríamos en el método setContentView(), que usualmente se coloca al sobrescribir el método onCreate().
Como ya sabrás al implementar un interfaz, tenemos que implementar los métodos que esta trae, en este caso son:
  • onSurfaceCreated(), este método es llamado cuando la superficie (a.k.a. surface) es creada o es re-creada, como este método es llamado al inicio del renderizado, es un buen lugar para colocar lo que no variara en el ciclo del renderizado. Ejm: el color de fondo, la activación del índice z, etc, etc.
  • onDrawFrame(), este método en particular es el encargado de dibujar sobre la superficie (a.k.a. surface)
  • onSurfaceChanged(), este método es llamado cuando la superficie cambia de alguna manera, por ejemplo al girar el móvil y colocarlo en posición de paisaje.

MANOS A LA OBRA (O MÁS BIEN AL CÓDIGO) – LIENZO
Explicada y entendida la teoría anterior, vamos a echar mano al código, primero crearemos una actividad de manera regular, el único cambio que haremos en este caso, será al definir la Vista de contenidos.
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
 
public class TutOpenGL extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
   GLSurfaceView view = new GLSurfaceView(this);
     view.setRenderer(new OpenGLRenderer());
     setContentView(view);
    }
}
MANOS A LA OBRA (O MÁS BIEN AL CÓDIGO) – PINTOR
Siguiendo con la analogía de la primera parte, el lienzo está puesto, ahora vamos a codificar al pintor, en este caso es una clase extra que debe implementar la interfazGLSurfaceView.Renderer.
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
 
import java.util.Random;
import android.opengl.GLSurfaceView.Renderer;
 
public class MyRenderer implements Renderer{
 
 Random aleatorio = new Random();
 
 @Override
 public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
  float r = aleatorio.nextFloat();
  float g = aleatorio.nextFloat();
  float b = aleatorio.nextFloat();
  gl.glClearColor(r, g, b, 1.0f);
 }
 
 @Override
 public void onDrawFrame(GL10 gl) {
  gl.glClear(gl.GL_COLOR_BUFFER_BIT);
 }
 
 @Override
 public void onSurfaceChanged(GL10 gl, int width, int height) {
 }
 
}
Lo que conseguimos con este código es algo simple, cada vez que gires tu móvil del modo retrato al modo paisaje el fondo cambiará de color.
El método gl.glClearColor() establece el color que se utilizará para limpiar la pantalla, para motivos prácticos dejamos que se elija colores al azar, y es llamado a través del métodogl.glClear(), dado que el parámetro que le pasamos indica que limpie solo el buffer de color, que en este caso, esta en el método onDrawFrame().
Al momento de llamar al método onSurfaceChanged() se destruye la Vista de Contenido por lo que vuelve a llamar al método onCreate() y en este método se asigna el color de limpieza, por lo que cada vez que se gira el móvil, se vuelve a asignar un color diferente y es el que se muestra en pantalla.
Sin excepción alguna, todos los renderizados en 3D están formados por vértices, bordes y caras, resumiendo: polígonos. Es por ello que entender como se generan es una parte importante para entender como trabaja esta librería.
Para empezar con este tutorial no se necesitará de nuevas librerías.
LA TEORÍA POR DELANTE…
Antes de meter mano al código, deberás recordar tu teoría básica de geometría (no te asustes, cuando digo lo básico, es lo verdaderamente básico):
-          Vértice(s): Un vértice es la base de todo, a partir de esto se generan los demás partes que permitan graficar polígonos o modelos en 3D. Un vértice es el punto donde 2 o más bordes se encuentran.
-          Borde (o Línea): Un borde (o línea) es la unión de 2 vértices. En un modelo 3D, el borde puede ser compartido por 2 caras o polígonos.
-          Cara: Es uno (de los tantos) lados que pueda contar el polígono o el modelo en 3D. La modificación de una cara afecta a sus vértices y a sus bordes.
Todas estas definiciones anteriores son conocidas como las primitivas de dibujo.
MANOS AL CÓDIGO
Ahora que tenemos en cuenta la teoría básica sobre la que trabaja OpenGL, vamos a identificar como podemos generar cada uno de los puntos explicados en el segmento anterior:
-          Vértice: Para definir un vértice en OpenGL, se necesita establecer un array del tipo float con los puntos definidos en (x,y,z).
Ejm:
  • Para un punto sería:
float vertice[] = { 1f ,1f ,0f }; // el punto esta ubicado en la coordenada (1,1,0)
  • Para un cuadrado sería:
float vertices[] = {
 
-1f,  1f, 0f,           //vértice ubicado en (-1,1,0)
 
-1f, -1f, 0f,          //vértice ubicado en (-1,-1,0)
 
1f, -1f, 0f,           //vértice ubicado en (1,-1,0)
 
1f, 1f, 0f              //vértice ubicado en (1,1,0)
 
}
  • Para una pirámide de base triangular sería:
float vertices[] = {
 
-1f,   -1f, 0f,        //vértice ubicado en (-1,-1,0)
 
1f,   -1f, 0f,         //vértice ubicado en (1,-1,0)
 
0f,  0.8f, 0f,         //vértice ubicado en (0,0.8, 0)
 
0f,    0f, 2f          //vértice ubicado en (0, 0, 2)
 
};
-          Borde: En OpenGL no se definen los bordes, estos quedan automáticamente establecidos al definir las caras (esto lo veremos en el sgte. punto). Para modificar un borde solo tienes que modificar los vértices que lo componen.
-          Cara: La definición de caras usando OpenGL es a través de triángulos, por ejemplo para definir un cuadro de vértices v0, v1, v2, v3, seria de la siguiente manera:
short caras[] = {
 
0, 1, 2,                  // primer triangulo formado
 
0, 2, 3                    // segundo triangulo formado
 
// juntando los dos triángulos forman un cuadrado
 
}
SE HORNEA DESPUÉS DE PREPARAR LA MASA
Con esto quiero decir, que el orden si importa al momento de generar las caras, porque es aquí cuando se especifica la dirección con la que se dibujaran (en la de las agujas del reloj o en contra de estas). Si quieres mejorar el rendimiento del renderizado, deberás graficar todos tus dibujos en la misma dirección, asi mediante código podremos esconder la parte trasera de tu dibujo cuando no sea necesario mostrarla.
La dirección del renderizado, mediante código, se realiza de la sgte. manera:
gl.glFrontFace(GL10.GL_CCW);
Para poder poder usar las caracteristicas de OpenGL, como las de esconder las caras que están del mirando a la pantalla, se deben activar primero y una vez aplicadas se deben desactivar.
De la siguiente manera:
gl.glEnable(GL10.GL_CULL_FACE);
y después indicar que lado debe esconder:
gl.glCullFace(GL10.GL_BACK);
y al final lo deshabilitamos:
gl.glDisable(GL10.GL_CULL_FACE);
MOMENTO DE MOSTRAR ALGO EN PANTALLA
Para poder mostrar el grafico cuyos vértices y caras hayamos definido, podemos utilizar 2 metodos:
-          public abstract void glDrawArrays(int mode, int first, int count)
-          public abstract void glDrawElements(int mode, int count, int type, Buffer indices)
El primer método dibuja la grafica según el orden como se haya definido en la construcción de los vértices. El segundo método necesita unos parámetros extras para graficar, necesita el orden en el que se graficaran los vértices.
Lo único común a ambas funciones es que ambos necesitan saber que primitivas deben renderizar. Hay varias formas de renderizar las primitivas:
-          GL_POINTS: Renderizar solo los vértices.
-          GL_LINE_STRIP: Renderizar segmentos de línea conectados entre si por un vértice.
-          GL_LINE_LOOP: Renderiza igual que el anterior, pero une el punto final con el punto inicial.
-          GL_LINES: Renderiza segmentos de línea entre 2 vertices independientes de otros vértices.
-          GL_TRIANGLES: Renderiza superficies mediante triángulos usando 3 puntos de referencia.
-          GL_TRIANGLE_STRIP: Renderiza triángulos continuos usando 3 puntos de referencia
-          GL_TRIANGULE_FAN: Renderiza triángulos usando un punto en común, a modo de abanico
CODIGO PURO Y DURO
Para este pequeño ejemplo necesitaremos crear 3 archivos:
-          La actividad principal (puede ser la utilizada en el post anterior)
-          El renderizador (el archivo que implementara la interfaz GLSurfaceView.Renderer)
-          y una clase que crearemos indicando numero de vértices, caras y demás características del dibujo que queramos ver en pantalla.
La actividad principal:
import android.app.Activity;
 
import android.opengl.GLSurfaceView;
 
import android.os.Bundle;
Con esto terminamos las importaciones que necesitamos para que no haya problemas en el código.
public class OpenGLProjectActivity extends Activity {
 
@Override
 
protected void onCreate(Bundle savedInstanceState) {
 
super.onCreate(savedInstanceState);
 
GLSurfaceView surface = new GLSurfaceView(this);
 
MyRenderer renderer = new MyRenderer();
 
surface.setRenderer(renderer);
 
setContentView(surface);
 
}
 
}
En el método onCreate() instanciamos una superficie sobre la que dibujaremos y nuestro renderizado, que será el encargado de dibujar.
El renderizador:

import javax.microedition.khronos.egl.EGLConfig;
 
import javax.microedition.khronos.opengles.GL10;
 
import android.opengl.GLSurfaceView.Renderer;
 
import android.opengl.GLU;
Importaciones necesarias para que el codigo compile sin problemas.
public class MyRenderer implements Renderer{
 
Piramide piramide = new Piramide();
 
@Override
 
public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
 
// Establece el color de fondo (r,g,b,a)
 
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
 
// Habilita el sombreado suave
 
gl.glShadeModel(GL10.GL_SMOOTH);
 
// Configura el buffer de profundidad
 
gl.glClearDepthf(1.0f);
 
// Habilita el testeo de profundidad
 
gl.glEnable(GL10.GL_DEPTH_TEST);
 
// El tipo de testeo de profundidad a hacer
 
gl.glDepthFunc(GL10.GL_LEQUAL);
 
// Calculo de perspectivas
 
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
 
}
Como lo habias indicado en el primer tutorial, en el método onSurfaceCreated() se establecen los valores cuya variación será poca o nula durante la ejecución del programa, en este caso establecemos:
-          el color de fondo mediante gl.glClearColor()
-          el sombreado suave en el renderizado mediante gl.glShadeModel()
-          el buffer de profundidad mediante gl.glClearDepth()
-          un parámetro de renderizado,el testeo de profundidad, mediante gl.glEnable()
-          el tipo de testeo de profundidad mediante gl.glDepthFunc()
-          la calidad del color y la interpolacion de las coordenadas de la textura mediante gl.glHint() y lo ponemos en la máxima calidad posible.
@Override
 
public void onDrawFrame(GL10 gl) {
 
// Limpia la pantalla y el buffer de profundidad
 
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
 
// Reemplaza la matriz actual con la matriz identidad
 
gl.glLoadIdentity();
 
// Traslada 4 unidades en el eje Z
 
gl.glTranslatef(0, 0, -4);
 
// Dibuja nuestra piramide
 
piramide.draw(gl);
 
}
En el método onDrawFrame(), insertamos el código que queremos que se ejecute durante el renderizado, por lo que hacemos lo sgte:
-          Limpiamos la pantalla y el buffer
-          Cargamos la matriz identidad
-          Trasladamos el dibujo 4 unidades en el eje z
-          Llamamos al metodo draw de nuestro objeto Piramide, instanciado anteriormente.
@Override
 
public void onSurfaceChanged(GL10 gl, int width, int height) {
 
// Establece el puerto de vista actual  al nuevo tamaño
 
gl.glViewport(0, 0, width, height);
 
// Selecciona la matriz de proyeccion
 
gl.glMatrixMode(GL10.GL_PROJECTION);
 
// Reinicia la matriz de proyeccion
 
gl.glLoadIdentity();
 
// Calcula la proporcion del aspecto de la ventana
 
GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f,100.0f);
 
// Selecciona la matriz de la vista del modelo
 
gl.glMatrixMode(GL10.GL_MODELVIEW);
 
// Reinicia la matriz de la vista del modelo
 
gl.glLoadIdentity();
 
}
 
}
En el método onSurfaceChanged() colocamos los ajustes que queramos hacer cuando la superficie sobre la que dibujamos sufra alguna modificación. En este caso:
-          Utilizamos gl.glViewPort() para afinar la transformación de los ejes x,y de las coordenadas de un dispositivo a las de una ventana
-          gl.glMatrixMode() para especificar a que matriz se le van a aplicar los cambios posteriores
-          Gl.glLoadIdentity() para reiniciar la matriz indicada en el método anterior
-          GLU.gluPerspective() para calcular el ratio de la ventana
-          Gl.glMatrixMode, de nuevo, para seleccionar la matriz de vista de modelo
-          Gl.glLoadIdentity para reiniciar la matriz de la vista del modelo
Nuestra clase:
Para este tutorial graficaremos una pirámide triangular, por lo que nuestra clase se llamara (a que no adivinas) Piramide.
import java.nio.ByteBuffer;
 
import java.nio.ByteOrder;
 
import java.nio.FloatBuffer;
 
import java.nio.ShortBuffer;
 
import javax.microedition.khronos.opengles.GL10;
 
public class Piramide {
 
//Nuestros Vertices
 
private float vertices[] = {
 
-1f, -1f, 0f,
 
1f, -1f, 0f,
 
0f, 0.8f, 0f,
 
0f,  0f, 2f
 
};
 
Definimos los vértices de nuestra pirámide en (x,y,z)
 
// La forma como vamos a conectarlos
 
private short caras[] = {
 
0,1,2,
 
0,2,3,
 
0,1,4,
 
1,2,4,
 
2,3,4,
 
3,0,4
 
};
 
Definimos que vértices vamos a unir formando las caras triangulares
 
private float colors[] = {
 
1f, 0f, 0f, 1f,
 
0f, 1f, 0f, 1f,
 
0f, 0f, 1f, 1f,
 
1f, 0f, 1f, 1f
 
};
 
Definimos los colores que vamos a utilizar en cada vertice
 
private FloatBuffer vertexBuffer;
 
private FloatBuffer colorBuffer;
 
private ShortBuffer indexBuffer;
 
public Piramide() {
 
// un float es de 4 bytes, por lo que multiplicaremos el numero de vertices por 4
 
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
 
vbb.order(ByteOrder.nativeOrder());
 
vertexBuffer = vbb.asFloatBuffer();
 
vertexBuffer.put(vertices);
 
vertexBuffer.position(0);
 
// un short es de 2 bytes, por lo que multiplicaremos el numero de vertices por 2
 
ByteBuffer ibb = ByteBuffer.allocateDirect(caras.length * 2);
 
ibb.order(ByteOrder.nativeOrder());
 
indexBuffer = ibb.asShortBuffer();
 
indexBuffer.put(caras);
 
indexBuffer.position(0);
 
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
 
cbb.order(ByteOrder.nativeOrder());
 
colorBuffer = cbb.asFloatBuffer();
 
colorBuffer.put(colors);
 
colorBuffer.position(0);               }
En el constructor de nuestra clase inicializaremos las variables, de vértices, caras y colores, de manera que OpenGL pueda interpretarlas correctamente
public void draw(GL10 gl) {
 
// Contra las agujas del reloj
 
gl.glFrontFace(GL10.GL_CCW);
 
// Habilitar el sacrificio de caras a ocultar
 
gl.glEnable(GL10.GL_CULL_FACE);
 
// Aca se indica que cara se sacrificara, en este caso, la de atras
 
gl.glCullFace(GL10.GL_BACK);
 
// Habilitar el buffer de vertices para la escritura y cuales se usaran para el renderizado
 
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
 
// Especifica la localizacion y el formato de los datos de un array de vertices a utilizar para el renderizado
 
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
 
// Habilita el buffer para el color del grafico
 
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
 
// Señala donde se encuentra el buffer del color
 
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
 
//Dibujamos las superficies
 
gl.glDrawElements(GL10.GL_TRIANGLES, caras.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);
 
// Desactiva el buffer de los vertices
 
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
 
//Desactiva la caracteristica de sacrificios de las caras
 
gl.glDisable(GL10.GL_CULL_FACE);
 
// Desahilita el buffer del color
 
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);          }
 
}
En este ultimo método de nuestra clase habilitamos todas las caracterisiticas explicadas en el tutorial para que el dibujo se pueda hacer de manera correcta.
El resultado final de todo este codigo es el siguiente:
Si te gusto el tutorial, compártelo, cualquier duda o pregunta pueden dejarla en los comentarios.

viernes, 4 de mayo de 2012

AndEngine, otro motor de juegos 2D OpenGL


Esta semana estaremos hablando acerca de varios frameworks y SDK’s enfocados al desarrollo de juegos y continuando con esta serie, hoy vamos a platicar acerca de uno de los preferidos por los desarrolladores: AndEngine, un motor de videojuegos 2D paraAndroid.

Una de las características que más resalta de AndEngine es que es de código abierto y que en sí, se trata de una implementación 2D de OpenGL para Android por lo que utilizaremos puramente el lengauej Java, a diferencia de los motores Unity3D y Shiva3D con los que podíamos trabajar con lenguajes como C#, Python, o incluso Javascript.
Uno de los puntos en contra de AndEngine es que la documentación “oficial” es aún muy pobre, por lo ni siquiera en la Wiki lograremos encontrar toda la información que necesitemos. Afortunadamente, en la web podemos encontrar algunos links muy interesantes a tutoriales para crear juegos con AndEngine y con ellos podremos iniciarnos con éxito en este motor de juegos.

Conceptos básicos de AndEngine
Para empezar a familiarizarnos con esta herramienta, hay que saber que existe una terminología propia de AndEngine, y a continuación menciono los conceptos básicos que debes dominar según el sitio de Droideando:
  • BaseGameActivity: El BaseGameActivity es la raíz del juego, que contiene el motor y crea la vista donde se va a dibujar todo. Hay siempre exactamente un solo Engine por cada BaseGameActivity.
  • Engine: El Engine es el motor interno del juego, se encarga de ir dibujando en pantalla y actualizando objetos en la escena, que contiene todo el contenido que tu juego lleva. Normalmente hay una escena por Engine, a menos que vayas a usar unSplitScreenEngines.
  • IResolutionPolicy: Una implementacion de IResolutionPolicy interface es parte delEngineOptions. Te hace abstraerte de la resolución del terminal, tú trabajas para una resolución y el AndEngine se encarga del resto.
  • Camera: Un objeto Camera define el rectángulo visible actualmente de la escena actual, no tiene por qué ser la escena completa. Normalmente hay una cámara por escena. Hay subclases específicas que permiten hacer zoom y mover la cámara suavemente.
  • Scene: La clase Scene es el contenedor para todos los objetos que se van a dibujar en la escena. Una escena puede tener Layers, que son capas para ordenar objetos. Hay subclases de la Scene como CameraScene/HUD/MenuScene que tienen comportamientos específicos.
  • Entity: Una entidad es un objeto que puede ser dibujado, como Imágenes, rectángulos, Texto, Líneas. Una entidad tiene posición/rotación/zoom/color…
  • Texture: Una textura es una imagen que se guarda en memoria. En Android, las imágenes deben ser una potencia de 2.
  • ITextureSource: Una implementacion de ITextureSource interface se encarga de cargar una imagen en una posición en la textura.
  • TextureRegion: Una TextureRegion define un rectángulo en una imagen. LasTextureRegion se usan por Sprites para usar una imagen grande en la que guardamos muchas imágenes pequeñitas.
  • PhysicsConnector: Motor de físicas integrado en el Engine.

¿Por dónde empiezo?
Lo primero es descargarte el código desde la página oficial de AndEngine. Aquí encontrarás links hacia el foro y el blog del proyecto así como un código QR que te enlaza a una aplicación que te puedes descargar en tu Android para ver algunos ejemplos de lo que puedes hacer con AndEngine.

Links de referencia
Si quieres empezar a crear demos con AndEngine te comparto unos links que te pueden servir de mucha ayuda para lograrlo.
  • Droideando. Un excelente blog enfocado a publicar series de tutoriales acerca de AndEngine y tips muy útiles para desarrollo de juegos en Android.
  • Guía tutorial para programar juegos 2D en Android utilizando AndEngine. Este es uno de los recursos que más recomiendo que revises ya que se explica desde cómo enlazar tu proyecto con la librería, la estructura básica de un juego, implementación de características básicas y cómo mejorar el rendimiento de un juego.
  • AndEngine – Examples. Aplicación Android con ejemplos de AndEngine para que los veas corriendo en un entorno completamente “real”.
  • Código del proyecto. Aquí encontrarás varias extensiones que puedes utilizar en tus proyectos y una serie de video dónde se muestra su uso.
  • Foro y Blog oficiales.
  • Artículo “Eligiendo un framework de desarrollo para Android”. Este artículo expone una comparativa entre varios frameworks de los cuáles podemos elegir para crear juegos. Te ayudará a decidir cuál es que más se acomoda a tus necesidades.

Seguiremos platicando acerca de otros frameworks que existen para desarrollar videojuegos en Android. Si actualmente estás desarrollando juegos, ¿qué herramienta utilizas?.

miércoles, 2 de mayo de 2012

LibGDX: comenzando desde cero los videojuegos


Una de las cosas que hizo que decida utilizar Libgdx para mi primer juego 2d Android es el modulo scene2d. Este modulo consiste en una serie de clases que facilitan muchisimo tareas como mostrar imagenes en pantalla, moverlas, rotarlas, animarlas, etc… es decir, casi todo lo que necesitamos a la hora de programar un juego sencillo.
Básicamente la idea de Scene2d es un escenario al que le podemos agregar actores. Estos actores pueden ser por ejemplo imagenes y tienen propiedades como x e y que indican en que parte del escenario están ubicados. Modificando estas propiedades podemos hacer que los actores cambien de posición o se vayan moviendo. En definitiva, la idea de los actores es igual a los Movieclips de Actionscript.
A continuación les voy a mostrar con un ejemplo y sencillos pasos como empezar con scene2d.

Crear el escenario

Para comenzar declaramos nuestro escenario con sus medidas
stage = new Stage(320, 480, true);

Agregar un actor

Creamos un actor de tipo Imagen, lo posicionamos y finalmente lo agregamos al escenario.
TextureRegion texture = new TextureRegion(new Texture(
             Gdx.files.internal("data/jugador.png")), 0, 0, 40, 40);
 
image = new Image("TestImage", texture);
image.x = 0;
image.y = 0;
 
stage.addActor(image);

Renderizar el escenario con los actores

Por ultimo, en nuestro metodo render lo unico que hacemos es limpiar la pantalla y llamar al metodo act de nuestro stage para que éste se ocupe de mostrar el/los actores en pantalla
@Override
public void render() {
 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
 stage.act(Gdx.graphics.getDeltaTime());
 stage.draw();
}

Agregando un poco de movimiento

Si queremos hacer que la imagen se mueva nada mas tenemos que modificar sus coordenadas y el stage se ocupara de mostrarla en su nuevo lugar.
@Override
public void render() {
 Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
 
 image.y += 100 * Gdx.graphics.getDeltaTime();
 
 stage.act(Gdx.graphics.getDeltaTime());
 stage.draw();
}
Así de facil. El ejemplo es muy básico pero muestra lo sencillo que es todo con scene2d. En un próximo articulo ampliaré un poco mas el tema con una clase derivada de Image, drag & drop y alguna que otra cosita mas.
Codigo fuente y proyectos para probar: Descargar.
Para aquellos que nunca hayan probado Libgdx les recomiendo que hagan el tutorial deHelloWorld, les va a ayudar a entender este tutorial. Otra opcion es este video tutorial.

martes, 1 de mayo de 2012

Mayo: videojuegos en Android, a full LibGDX !!


Uno de los ámbitos más populares para crear aplicaciones en Android (y en cualquier otra plataforma móvil) es sin duda la de los juegos. Hoy vamos a conocer una herramienta que te puede ser de mucha utilidad si lo que queres es dedicarte a la creación de juegos en Android.
Se trata de Libgdx, un framework multiplataforma de desarrollo de juegos para Windows, Linux y Android. Está escrito en Java con una mezcla de C/C++ para dar soporte y rendimiento a tareas relacionadas con el uso de la física y procesamiento de audio. De esta forma, sólo tendrás que preocuparte por la parte que programaras en  Java mientras el framework se encarga de empaquetar todo el código nativo de las aplicaciones (juegos!).
Otra de las cosas interesantes de Libgdx es que te permite escribir, probar y depurar tu aplicación en la PC y utilizar el mismo código para Android. Esto es porque uno de los objetivos principales de este framework es brindar una arquitectura unificada para trabajar, garantizando el mismo comportamiento en todas las plataformas para las cuáles hayas creado tu juego. Genial ¿no?. Aún con esto, hay ciertas cosas que debes tomar en cuenta cuando estés trabajando un mismo juego para PC y para Android, ya que el rendimiento puede ser muy bueno en PC y muy malo en Android. Y ni hablar sobre el hardware especifico que tenemos en un Android, muy distinto a de una PC.
Las herramientas que nos brinda Libgdx son las siguientes:
  • Un framework que nos permitirá manejar el ciclo de vida (creación, pausa, reanudación y destrucción) de nuestra aplicación/juego.
  • Un módulo de gráficos que nos proporciona una forma de dibujar objetos en la pantalla.
  • Un módulo de audio para reproducir música y efectos de audio.
  • Un módulo de entrada para recibir toda la información del usuario proveniente del mouse, teclado, pantalla táctil, acelerómetro, etc.
  • Un módulo de I/O para leer y escribir datos como texturas, mapas o archivos de configuración.

¿Por dónde empiezo?
Lo primero es descargarnos el framework desde la página del proyecto. Entonces, ahora veamos un video introductorio de 13 minutos para conocer todo el proceso de instalación y configuración de Libgdx con Eclipse y una pequeña demo por medio de un ejemplo que te permitirá mira y percibir rapidamente los componentes básicos del framework y asi empezar a pensar como crear tus propios demos de juegos.
Links de referencia:
  • Wiki. Te recomiendo que explores toda la página del proyecto de Libgdx, y en especial del apartado de la Wiki que contiene información General básica y en la que también encontrarás la estructura básica de un proyecto con Libgdx;  la Guía del desarrollador con información de los módulos que contiene el framework y las consideraciones a tomar para el uso óptimo en tus juegos, las herramientas que puedes utilizar y el apartado de Tutoriales que se encuentran divididos en categorías de Beginner, Intermediate y Misc.
  • Javadoc. La documentación de referencia que te permitirá navegar y consultar información de alguna clase en específico de Libgdx.
  • Foro. Cuando empiezas a conocer un proyecto uno de los pilares más importantes son los foros en dónde puedes encontrar información de otros usuarios que tal vez ya resolvieron una duda que te aqueja ahora y también si tienes la oportunidad de aportar algo hazlo.
  • Videotutoriales. Échale un ojo a esta serie de videotutoriales para que empieces con lo básico de Libgdx.
  • Badlogic Games. En esta página encontrarás ligas de referencia a documentación y a la comunidad que apoya este proyecto.
Como vemos, información de referencia existe, ahora es cuestión de que te animes a empezar a crear tus demos. Existen otros frameworks y SDK’s para desarrollo de juegos en Android y sin quitarle lo valioso a cada herramienta existente, te invito a que conozcas cada uno de estos framework, no existe "la bala de plata" en Android, o el "Cocos 2d" que tenemos en iOS, pero "para Android", yo lo que les recomiendo es que, investiguen cuales existen, y al final usen el que más les sirva a ustedes, para el juego que tengan en mente.