martes, 4 de febrero de 2014

Animaciones

Animaciones

Saludos de nuevo a todos, después de algun tiempo ocupado vamos a hablar de animaciones finalmente haremos un pequeño tutorial sobre un actor animado, os mostraré que utilizo para diseñar mis propios sprites.

Como podemos observar en libgdx no podemos integrar una imagen animada directamente y tenerlo listo por arte de magia, debemos crear una secuencia de imágenes y dibujarlas una a una para crear la sensación de movimiento que necesitamos.

He descargado un sprite de opengameart.org para mostraros y a la vez hacer pruebas, podeís descargarlo aqui.

http://opengameart.org/sites/default/files/32x40%20sprite%20base.png

Bien, como ya sabemos, libgdx únicamente nos permite trabajar con texturas POT (potencia de 2) y ésta imagen no nos sirve para empezar a utilizarla, para ello la he retocado un poco haciendola del tamaño adecuado y le he eliminado el fondo.

A partir de aqui vamos a preparar nuestra animación, para crear nuestra animación libgdx nos va a pedir 2 cosas, el tiempo entre frame y frame y un array de frames que contendra nuestras animaciones. En ésta imagen como observamos tenemos 4 animaciones, cada una hacia un lado diferente de la pantalla.

Escribo la classe con las explicaciones en los comentarios.

package com.Firedark.libgdxspain;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
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;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;

public class Human extends Actor {
   
    private LibgdxSpain game;
    private Texture Thuman;
    private TextureRegion[] up,down,left,right;
    private TextureRegion[][] tmp;
    private Animation Aup,Adown,Aleft,Aright;
    private float stateTime;
    private TextureRegion currentFrame;
    private Vector2 velocity;
   
    public Human(LibgdxSpain game){
        
         this.game = game;
        
         Thuman = game.assets.manager.get("data/Images/human.png");
         //tmp es un array bidimensional donde alojamos nuestra imagen cortada a trozos con el método split de TextureRegion.
         //en éste caso lo cortamos en 8 columnas y 1 fila, lo hago así porque un sprite puede tener varias filas y columnas
         //en éste caso no sería necesario.
         tmp = TextureRegion.split(Thuman, Thuman.getWidth() /
                         8, Thuman.getHeight() );
               
                 //Arrays de Frames, creamos 4 arrays de TextureRegion de 2, y le añadimos las posiciones de las texturas en tmp.
               
                 up = new TextureRegion[2];
                 up[0] = tmp[0][0];
                 up[1] = tmp[0][1];
                 down = new TextureRegion[2];
                 down[0] = tmp[0][4];
                 down[1] = tmp[0][5];
                 left = new TextureRegion[2];
                 left[0] = tmp[0][6];
                 left[1] = tmp[0][7];
                 right = new TextureRegion[2];
                 right[0] = tmp[0][2];
                 right[1] = tmp[0][3];
               
                 //Creamos las classes Animation, con el tiempo entre frame y frame 0.2f y nuestros arrays.
                 Aup = new Animation(0.4f, up);
                 Adown = new Animation(0.4f, down);
                 Aleft = new Animation(0.4f, left);
                 Aright = new Animation(0.4f, right);
               
                 //El statetime imaginarlo como un tiempo indefinido que usaremos para ir moviendo nuestros sprites.
                 stateTime = 0f;
               
                 //Características de nuestro Actor
               
                 setPosition(400,400);
                 setHeight(64);
                 setWidth(32);
                 velocity = new Vector2(0,0);
              
                 //Textura por defecto
                 currentFrame = down[0];
               
    }
   
    @Override
    public void draw(SpriteBatch batch, float parentAlpha){
       
      
        //Vamos a controlar a nuestro humano a base de teclado, no voy a hacer un controlador bueno
        //solo algo funcional para probar la animacion.
      
        velocity.x = 0;
        velocity.y = 0;
        if(Gdx.input.isKeyPressed(Keys.W) & !Gdx.input.isKeyPressed(Keys.S) & !Gdx.input.isKeyPressed(Keys.A) & !Gdx.input.isKeyPressed(Keys.D)) velocity.y = 1;
        if(Gdx.input.isKeyPressed(Keys.A) & !Gdx.input.isKeyPressed(Keys.S) & !Gdx.input.isKeyPressed(Keys.D) & !Gdx.input.isKeyPressed(Keys.W)) velocity.x = -1;
        if(Gdx.input.isKeyPressed(Keys.S) & !Gdx.input.isKeyPressed(Keys.W) & !Gdx.input.isKeyPressed(Keys.A) & !Gdx.input.isKeyPressed(Keys.D)) velocity.y = -1;
        if(Gdx.input.isKeyPressed(Keys.D) & !Gdx.input.isKeyPressed(Keys.S) & !Gdx.input.isKeyPressed(Keys.A) & !Gdx.input.isKeyPressed(Keys.W)) velocity.x = 1;
      
      
        //Movemos nuestro Sprite
        setX(getX() + velocity.x);
        setY(getY() + velocity.y);
      
        //comprobamos la velocidad y gracias al método getKeyFrame de la clase Animation recuperamos el frame que necesitamos en cada momento.
        //El true representa que es un movimiento cíclico.
      
        if(velocity.x> 0 & velocity.y == 0)    currentFrame = Aright.getKeyFrame(stateTime,true);
        if(velocity.x< 0 & velocity.y == 0)    currentFrame = Aleft.getKeyFrame(stateTime,true);
        if(velocity.y> 0 & velocity.x == 0)    currentFrame = Aup.getKeyFrame(stateTime,true);
        if(velocity.y< 0 & velocity.x == 0)    currentFrame = Adown.getKeyFrame(stateTime,true);
      
        //actualizamos nuestro stateTime y dibujamos el currentFrame.
        stateTime += Gdx.graphics.getDeltaTime();  
        batch.draw(currentFrame, getX(), getY(), getWidth()*2,getHeight()*2);

        //Listo ya tenemos nuestro Sprite funcionando.
    }
}


A continuación un video con nuestro resultado final. No és un resultado increible ya que con el sprite de 2 imágenes queda un poco raro, pero añadirle 2 frames más por paso o probar con varios sprites que encontreís en la red, ya que es la mejor manera de aprender.








7 comentarios:

  1. Muy buena explicacion, por favor sigue asi, Animo.

    ResponderEliminar
  2. Gracias, recien empiezo en esto de libgdx :)

    ResponderEliminar
  3. Pero ahora se puede evitar usar potencias de 2, usando OpenGL2, además, en los mismos foros están pensando retirar el soporte a OpenGL1. No hace falta decir excelente guía, estoy aprendiendo su uso pero mi problema es cómo ordenar un proyecto en paquetes para que se vea más ordenado, ¿podría hacer un tutorial tomando como base a superKoalio porfavor?

    ResponderEliminar
  4. Genial, a ver cuando te animas y subes otro tutorial ;)

    ResponderEliminar
  5. Estupendo trabajo! muchas gracias!
    Yo estoy teniendo muchísimos problemas para integrar admob (con el google play services) con libgdx,¿podrías hacer una entrada sobre esto?. Muchas gracias, un saludo!

    ResponderEliminar
    Respuestas
    1. Aqui puedes encontrar como integrar Admob con google play services http://goo.gl/929oCr

      Eliminar