viernes, 4 de marzo de 2016

Sobre como animar personajes(Sprites) en Love2d


Este es un pequeño ejemplo creado de la manera más fácil que supe, sobre como animar personajes(Sprites) en Love2d.

Dejo el código tal cual lo escribí, totalmente comentado. Me puedo equivocar en muchas cosas pues este ejemplo está creado a partir de mi propia exploración.

Y aquí va un archivo con todo el ejemplo listo para ejecutarse en Love2d. Al pulsar sobre el enlace, este os llevará hasta la página de safecreative.org, a la izquierda veréis un botón que dice, descargar esta obra, desde ese botón el ejemplo comenzará a ser descargado. Por ahora no tengo un lugar mejor donde colgarlo.



ejemplo animación (descargar)


Quizás en un futuro lo implemente a modo de clase para facilitar el uso de este ejemplo. Por ahora aquí va lo aprendido sobre animaciones en Love2d


--[[
     Esta función se encarga de crear las tablas que contendrán los fotogramas a usar.
    
    Datos que recibe:
   
    anchoFotograma: Es el ancho interno para cada uno de los fotogramas contenidos en la imagen
    altoFotograma: Es el ancho interno para cada uno de los fotogramas contenidos en la imagen
    filas: número de filas que contiene la imagen
    columnas: número de columnas que contiene la imagen
    imagen: Es la imagen que contiene todas los fotogramas a crear
]]--
function crear_fotogramas(anchoFotograma,altoFotograma,filas,columnas,imagen)

    indiceFilas=1
    --Contiene todas las animaciones contenidas dentro de una imagen   
    tablaDeFotogramas={}
    --Contiene una de las animaciones, dada, en una de las filas de la imagen
    tira={}
   
   
    --[[Para manejarnos por el ancho y alto interno de la imagen y así poder relizar los cortes donde nosotros queremos
    vamos a usar las dos variables: punteroX,punteroY]]--
    punteroX=0
    punteroY=0
   
   
    --[[Vamos a usar dos bucles for para ir generando los fotogramas de cada tira de animación,
    pero no vamos a recortar la imagen en si, lo que vamos a generar es la información de donde se encuentra cada
    fotograma dentro de la imagen. Para guardar esta información, vamos a usar el objeto quad que provee la biblioteca Lovë2d.
    Para generar un objeto Quad usaremos la siguiente sentencia:
   
        q=love.graphics.newQuad(posicionX,posicionY,ancho,alto,imagen:getDimensions())
   
        Esta función retornará un nuevo objeto quad con la información enviada
       
        posicionX,posicionY:Son las posiciones internas a la imagen donde realizaremos el recorte
        ancho,alto: Son las medidas internas a recortar
        imagen:getDimensions(): son las dimensiones de la imagen en total
    ]]--
    --Este for recorrerá las filas que contiene la imagen
    for f=1,filas do
   
        --Este for recorrerá cada uno de los fotogramas contenidos en una fila
        --creando en cada vuelta los quad necesarios para cada fotograma contenido en la fila
        --apuntada por punteroY
       
        --guarda una tabla con una de las animaciones
       
        tiraFotogramas={}
       
        --indice que se usará para indicar donde se guardará el fotograma en la tabla
        indice=1
       
        for c=1,columnas do
            --Creamos un Quad
           
            fotograma=love.graphics.newQuad(punteroX,punteroY,anchoFotograma,altoFotograma,imagen:getDimensions())
            tiraFotogramas[indice]=fotograma
            indice=indice+1   
           
            --guardamos el fotograma en la tabla de fotogramas
            --Sumamos a punteroX el ancho del fotograma para colocarlo en la siguiente posición
           
            punteroX=punteroX+anchoFotograma
        end
        tablaDeFotogramas[indiceFilas]=tiraFotogramas
        indiceFilas=indiceFilas+1
        --Al finalizar el anterior for, sumamos a punteroY el alto del fotograma para colocarlo en la siguiente fila
        punteroY=punteroY+altoFotograma
        --Pasamos el punteroX a cero para colocarlo al principio de la fila
        punteroX=0
    end
    return tablaDeFotogramas
end

--cargamos todos los recursos necesarios para ejecutar el ejemplo
function love.load()

    --Variable que indica cuantos píxeles se va a desplazar el personaje por la pantalla
    velocidad=120
   
    --[[variable que contendrá un valor expresado en milisegundos
    que servirá para realizar un pequeño retardo entre
    fotograma y fotrograma. Este retardo hará que la animación quede más estética.]]--
    retardo=50
   
    --Posición del personaje en pantalla
    posicionX=400
    posicionY=300
   
    --Anclaje del personaje
    anclaX=100
    anclaY=200
   
    --[[Las dos imágenes que usaremos para realizar las
    animaciones]]--
    caminandoImagen=love.graphics.newImage("caminando.png")
    paradoImagen=love.graphics.newImage("parado.png")
   
   
    --Tablas que contendrán los cuadros de imagen de cada animación
    caminando=crear_fotogramas(200,200,4,8,caminandoImagen)
    parado=crear_fotogramas(200,200,1,4,paradoImagen)
   
    --Variable que contendrá true si nuestro personaje está caminando y false cuando esté parado.
    estaCaminando=false
   
    --Variable que indicará la dirección en la que está mirando el personaje
    direccion=1
   

   
    -- Variable que contendra la suma del tiempo que va transcurriendo en cada ejecución de la funcion love.update(dt)
    sumaRetardo=0
   
    --Variable que contiene el fotograma actual si el personaje se está animando
    fotogramaActual=1
   

end


--Función que se encarga de actualizar el ejemplo
--Esta función se ejecuta cada x tiempo mientras el programa está en ejecución
function love.update(dt)
    if (love.timer) then
        --[[Generamos lapso de tiempo para controlar los cuadros por segundos
        a los que se ejecutara este ejemplo, en este caso a 30 fotogramas.
        El máximo de fotogramas a los que he visto ejecutarse Lovë2d es a 60,
        en estos momentos desconozco si se puede ejecutar a más fotogramas o si este es el
        máximo permitido.
        Para limitar la tasa de Fotogramas usaremos la siguiente sentencia.]]--
        love.timer.sleep(1/30)
       
        --[[La variable dt lleva el tiempo transcurrido desde la última vez que
        se ejecutó la función love.update. al multiplicarlo por mil, obtenemos el
        tiempo  expresado en milisegundos (Si no me equivoco)]]--
        tiempo=dt*1000
       
       
        --[[
                La siguiente condicional nos servirá para
                controlar que tecla de dirección se está pulsando o si por el contrario
                no se esta pulsando ninguna tecla.
        ]]--
       
        estaCaminando=true
        if love.keyboard.isDown("up") then
            direccion=1
            posicionY=posicionY-velocidad*dt
        elseif love.keyboard.isDown("down") then
            direccion=3
            posicionY=posicionY+velocidad*dt
        elseif love.keyboard.isDown("right") then
            direccion=2
            posicionX=posicionX+velocidad*dt
        elseif love.keyboard.isDown("left") then
            direccion=4
            posicionX=posicionX-velocidad*dt
        else
            estaCaminando=false
        end
       
        --[[Esta es la porción de código encargada de controlar el tiempo de ejecución
        de la animacón mientras se está ejecutando]]--
        if(estaCaminando==true) then
           
            --Vamos sumando el tiempo a sumaRetardo para controlar el siguiente salto de fotograma
            sumaRetardo=sumaRetardo+tiempo
       
            --Si el tiempo transcurrido supera el tiempo indicado en retardo
            --pasaremos al cambio de fotograma
            if (sumaRetardo>=retardo) then
                sumaRetardo=0
                fotogramaActual=fotogramaActual+1
                --en lua la expresión #tabla nos dará el número de elementos contenidos en la misma
                --Si el fotograma actual supera al máximo de fotogramas contenidos en la animación
                --pasaremos a mostrar otra vez el primer fotograma
                if(fotogramaActual>#caminando[direccion]) then
                    fotogramaActual=1
                end
            end
        end
    end
end

--función encarada de dibujar la pantalla del ejemplo
function love.draw()

    --Creamos las posiciones finales teniendo en cuenta la posicion y el ancla
    finalX=posicionX-anclaX
    finalY=posicionY-anclaY
   
   
    if(estaCaminando==true) then
        --si el personaje está caminando mostramos la animación teniendo en cuenta
        --la dirección y el fotogramaActual
        love.graphics.draw(caminandoImagen,caminando[direccion][fotogramaActual],finalX,finalY)
    else
        --Si el personaje está parado mostraremos su imagen teniendo en cuenta la dirección
        love.graphics.draw(paradoImagen,parado[1][direccion],finalX,finalY)
    end
end

No hay comentarios:

Publicar un comentario