Si deseo crear un juego tarde o temprano tendré que verme las caras con la creación de sprites para el juego y sin duda aunque con talento salen mucho mejor estas cosas siempre me han gustado.

Es cierto, le tenía ganas ya al PixelArt y a la animación y gracias a los sprites en juegos he podido tener dos tazas de cada una. No ha sido demasiado problemático excepto al principio para encontrar unas proporciones que sean de mi gusto y no crear estrambóticos diseños.

La creación la he realizado con GIMP y ha sido bastante sencillo gracias al tratamiento de que dispone. Trabajo por capas, cada capa es un fotograma de la animación, una vez todo hecho un bonito fondo para que no se superponga al hacer el .gif y listo. Una vez comprobado el resultado solo restaría crear la malla para utilizar en XNA, en mi caso concreto ahora mismo.

El resultado es gracioso y le tengo bastante cariño, pese a no ser gran cosa… Pero me ha dado una experiencia mínima en esto de la animación que sin duda voy a explotar tanto como pueda.

Prueba de creación de sprite

En tener tiempo e ideas claras empezaré con la creación de personajes que ya serán utilizados con los fines en que empezó esto.

Una vez ya sabemos realizar animaciones con XNA y lo probamos nos damos cuenta de que algo falla porque la velocidad entre sprites es tan brutal que le va a dar una rampa en cualquier momento.

Por supuesto, esto se soluciona de un modo bastante sencillo que da mucho juego si se planea utilizarlo del mejor modo para nuestros propósitos.

Primero tendremos que crear los atributos necesarios para controlar la velocidad con la que se refresan los sprites en pantalla.

int tiempoUltimoFrame = 0;
int tiempoMSegundos = 100;

Con tiempoUltimoFrame guardaremos el tiempo transcurrido desde el último sprite dibujado mientras que en tiempoMSegundo tenemos asignado el tiempo que debe pasar entre sprites.

Ahora solo queda modificar el método Update para que dibuje cuando queremos cada sprite.

tiempoUltimoFrame += gameTime.ElapsedGameTime.Milliseconds;
if (tiempoUltimoFrame > tiempoMSegundos)
{
tiempoUltimoFrame = 0;
if (++currentFrame.X >= sheetSize.X)
{
currentFrame.X = 0;
}
}

He reutilizado el código sobre animación para ahorrarme trabajo dando supuesto que ya sabéis de que va. Simplemente con gameTime.ElapsedGameTime.Milliseconds controlamos el tiempo transcurrido y cuando es mayor al deseado se pasa al siguiente sprites restaurando el valor de tiempoUltimoFrame.

XNA: Animación

enero 27, 2009

Normalmente a la hora de hacer una animación con sprites se sueles utilizar lo que se denomina un sheet sprites que viene a ser una hoja de sprites.

Esta hoja de sprites es una cuadrícula donde se ponen de forma sucesiva cada uno de los sprites que queremos que formen la animación de modo que tan solo tengamos que movernos por el sprite y no ir cambiando de sprite. De este modo se gana velocidad y sencillez a la hora de animar.

Para poder dar un ejemplo de animación he optado por utilizar un sheet sprite ya hecho por Wishthechao y serán los sprites del personaje andando de cara.

wish

Como con cualquier textura la cargamos en el Content y la asignamos a una Textura2D. Una vez esto ya podemos pasar al tema de la animación.

Lo primero es saber como moverse dentro de la textura por ello utilizaremos tipo de dato Point como atributo de clase por su utilidad al disponer de X e Y.

Point frameSize = new Point(27, 40);
Point currentFrame = new Point(0, 0);
Point sheetSize = new Point(4, 0);

frameSize es el tamaño del sprite en ese frame, currentFrame cuenta los sprite ya dibujados hasta el frame actual y sheetSize como indica su nombre es el tamaño de la hoja de sprites.

Para dibujar los sprites utilizaremos el metodo de spriteBatch.Draw que venimos utilizando solo que en rectangle? Source Rectangle ya no pondremos null sino el tamaño del sprite que compone la hoja de sprites.

spriteBatch.Begin(SpriteBlendMode.AlphaBlend,
SpriteSortMode.BackToFront,
SaveStateMode.None);

spriteBatch.Draw(texture, Vector2.Zero,
new Rectangle(currentFrame.X * frameSize.X,
currentFrame.Y * frameSize.Y,
frameSize.X, frameSize.Y),
Color.White, 0f, Vector2.Zero,1f, SpriteEffects.None, 0f);

spriteBatch.End();

Como podéis observar el rectángulo creado para delimitar la parte visible del sheet sprite se forma a partir de las dos variables creadas anteriormente, currentFrame y frameSize. De este modo nos vamos moviendo a traves del sheet sprite sin tener que modificar el método Draw.

Aun falta la parte más importante que es la que generará el movimiento ya que de momento solo dibujará el primer sprite de la hoja de sprites.

Para ello debemos ir al método Update, sistema nervioso del juego, y hacer que con cada iteración vaya cambiando la posición del rectangulo que delimita el sprite en la hoja de sprites y que una vez recorrido los sprites deseados vuelva al inicio creando esa continuidad de movimiento deseada en este ejemplo.

if (++currentFrame.X >= sheetSize.X)
{
currentFrame.X= 0;
}

Dado que en este sheet sprite no nos movemos verticalmente para hacer la animación no es necesario modificar la componente Y en ningún caso pero de ser así sería igual de sencillo.

if (++currentFrame.X >= sheetSize.X)
{
currentFrame.X= 0;
if (++currentFrame.Y >= sheetSize.Y)
{
currentFrame.Y= 0;
}
}

Eso si, debemos indicarlo correctamente en sheetSize para que haga el recorrido deseado.