martes, 22 de marzo de 2016

Tutorial 6: Animaciones 2D

Hola buenas.
En esta ocasión veremos como animar sprites para nuestros personales, Es perfecto para crear ese dinamismo. En esta ocacion ocuparemos unos sprite descargados de: http://opengameart.org/content/jack-o-lantern-free-sprite 
Antes que todo vamos a preparar las imagenes, ya que son muy grandes. Con Gimp redimensionaremos las imagenes a 100x132 pixeles. Solo utilizaremos tres estados, el estar parado, caminando y corriendo.
Para lograr esto:

Manos a la obra.
Generamos el proyecto:

E importamos en eclipse:

En la carpeta assets de nuestro sub proyecto de android agregamos las carpetas "idle", "walk" y "run", donde estarán nuestras imágenes ya listas. Estas imágenes las van a encontrar en el código fuentes, que pondré al final.

Codigo:
Clase Tuto4;
package sv.chuckles.tuto4;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

public class Tuto4 extends ApplicationAdapter {
SpriteBatch batch;
float stateTime;
Animation aniIdle, aniWalk, aniRun;
@Override
public void create () {
batch = new SpriteBatch();
//carga de imaganes del descanso
TextureRegion[] keyFramesIdle = {
new TextureRegion(new Texture("idle/idle_1.png")),
new TextureRegion(new Texture("idle/idle_2.png")),
new TextureRegion(new Texture("idle/idle_3.png")),
new TextureRegion(new Texture("idle/idle_4.png")),
new TextureRegion(new Texture("idle/idle_5.png")),
new TextureRegion(new Texture("idle/idle_6.png")),
new TextureRegion(new Texture("idle/idle_7.png")),
new TextureRegion(new Texture("idle/idle_8.png")),
new TextureRegion(new Texture("idle/idle_9.png")),
new TextureRegion(new Texture("idle/idle_10.png"))
}; 
aniIdle = new Animation(0.075f, keyFramesIdle);
//carga de imaganes caminando
TextureRegion[] keyFramesWalk = {
new TextureRegion(new Texture("walk/walk_1.png")),
new TextureRegion(new Texture("walk/walk_2.png")),
new TextureRegion(new Texture("walk/walk_3.png")),
new TextureRegion(new Texture("walk/walk_4.png")),
new TextureRegion(new Texture("walk/walk_5.png")),
new TextureRegion(new Texture("walk/walk_6.png")),
new TextureRegion(new Texture("walk/walk_7.png")),
new TextureRegion(new Texture("walk/walk_8.png")),
new TextureRegion(new Texture("walk/walk_9.png")),
new TextureRegion(new Texture("walk/walk_10.png"))
}; 
aniWalk = new Animation(0.075f, keyFramesWalk);
//carga de imagenes corriendo
TextureRegion[] keyFramesRun = {
new TextureRegion(new Texture("run/run_1.png")),
new TextureRegion(new Texture("run/run_2.png")),
new TextureRegion(new Texture("run/run_3.png")),
new TextureRegion(new Texture("run/run_4.png")),
new TextureRegion(new Texture("run/run_5.png")),
new TextureRegion(new Texture("run/run_6.png")),
new TextureRegion(new Texture("run/run_7.png")),
new TextureRegion(new Texture("run/run_8.png"))
}; 
aniRun = new Animation(0.07f, keyFramesRun);

stateTime = 0;
}

@Override
public void render () {
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stateTime += Gdx.graphics.getDeltaTime();
batch.begin();
batch.draw(aniIdle.getKeyFrame(stateTime, true), 0, 0);
batch.draw(aniWalk.getKeyFrame(stateTime, true), 0, 170);
batch.draw(aniRun.getKeyFrame(stateTime, true), 0, 340);
batch.end();
}
@Override
public void dispose() {
batch.dispose();
}
}

Al ejecutarlo, veremos:

Explicación:
En la declaración de variables, veremos:
  1. float stateTime: Este flotante sera utilizado para acumular el tiempo que transcurre desde el ultimo frame en segundos. para que las animaciones sean pintadas de forma sincronizadas y correctas.
  2. Animation aniIdle, aniWalk, aniRun: Estas variables son las encargadas de almacenar todas nuestras imágenes y que ordenan las animaciones. La variable aniIdle es para el personaje en animación parado, aniWalk para la animación caminando y aniRun para la animación corriendo.
Método create:
  1. Lineas 20 a 31: Creamos un arreglo TextureRegion, donde cargaremos nuestras imágenes cuando el personaje esta parado, las imagines son del 1 al 10 de la carpeta "idle".
  2. Linea 32 - aniIdle = new Animation(0.075f, keyFramesIdle): Instanciamos la clase y le enviamos de parámetro tiempo en segundos que se ejecuta una frame después del otro. Para este caso 0.075 Seg. Y el ultimo parámetro es el arreglo de los imágenes.
  3. Lineas 35 a 47: Igual que el literal anterior. Con la variante que es para la animación de caminar.
  4. Lineas 50 a 60: Lo mismo solo que con la variante de las imágenes de correr.
Metodo render:
  1. stateTime += Gdx.graphics.getDeltaTime(): Es el acumulador ya descrito en la sección 1 de la Explicación.
  2. batch.draw(aniIdle.getKeyFrame(stateTime, true), 0, 0): Pintamos el frame actual, calculado por el stateTime en la posición (0,0), también se indica con el parámetro "true" que es un ciclo infinito, osea se repiten siempre las animaciones.
  3. batch.draw(aniWalk.getKeyFrame(stateTime, true), 0, 170): Igual que el literal anterior, solo que se pinta la animación de caminar en la posición (0,170).
  4. batch.draw(aniRun.getKeyFrame(stateTime, true), 0, 340): Igual que el literal anterior, solo que se pinta la animación de correr en la posición (0,340).
Ejecutamos esto, y veremos nuestras animaciones en acción xD
Ahora bien, que se necesita para pintar animaciones que estén de derecha a izquierda?
Pues hay dos formas, la primera es crear otra animación con las imágenes invertidas en X, pero esto conlleva que cargamos imágenes que ya existen y lo cual no es recomendable hacerlo por rendimiento. Así que la solución mas optima es utilizar nuestro objeto "batch", he indicar que pinte al revés nuestra animación.
Asi: 

batch.draw(aniRun.getKeyFrame(stateTime, true), 600 //posicion en X
,340 //posicion en Y
,-aniRun.getKeyFrame(stateTime).getRegionWidth() //ancho de la imagen
,aniRun.getKeyFrame(stateTime).getRegionHeight() //alto de la imagen
);
Aquí veremos una sobre carga del método "draw", lo importante es que recibe de parámetro extras las dimensiones de las animaciones, entonces ponemos negativo el ancho xD

Ejecutamos:

También lo podemos probar en el emulador o dispositivo:

Código fuente: https://github.com/Solidux/tuto-libgdxelsalvador.blogspot.com/tree/master/tuto4

Espero que todo haya quedado claro xD
Un Saludos

Sigueme en Twiter: https://twitter.com/libgdxESA

Si te gusta mi trabajo y quisieras ver mas y mas rápido, puedes donar $1.00 vía donación paypal:


No hay comentarios.:

Publicar un comentario