You don’t need an engine to do that, it’s pretty simple. And if your images are not gigantic (which they shouldn’t be if there are 160 of them) ImageIO will work just fine to load them.
You can use my Animation and AnimationSet class for the animations if you want. It’s pretty basic but it sounds like it will work for you. It functions like a hash map, so you just specify the name of the animation you want and it will play. Similarly you give each animation an integer priority so it will automatically prioritize animations as you would want. So like someone’s standing pose would be your default animation with a priority of 0, and then walk would have a priority of 1 and could therefore replace it, and kick would be 2, etc.
//A Vector2 is simply two floats.
//The Model.TARGET_DELTA has to do with my adaptive framerate. So basically if the delta was at
//0.4 and the target delta was 0.2, it would update the animations twice as quickly.
//The ImageManager just loads and holds images/sprites.
/**
* An Animaton contains an array of Textures that can be used for an Animation.
* @author Eli Delventhal
*/
public class Animation
{
/** The sprites that will be drawn. */
private String[] sprites;
/** The offsets at which to draw each sprite, automatically determined. */
private Vector2[] offsets;
/** The length of each frame in ticks. */
private int frameLength;
/** Whether or not this Animation loops. */
private boolean loops;
/** The priority of this Animation. */
private int priority;
/** How many ticks have gone by this frame. */
private float ticksThisFrame;
/** The frame number we're currently in. */
private int frameNumber;
/** Whether or not this Animation is finished. */
private boolean isFinished;
public Animation(String sprite, int prior)
{
this(new String[]{sprite},Integer.MAX_VALUE,true,prior);
}
/**
* Creates an Animation from an array of string references.
* @param images An array of Strings to use as keys for the ImageManager.
* @param delay The delay in ticks to have between frame changes.
* @param loop Whether or not this Animation loops.
* @param prior The priority of this Animation.
*/
public Animation(String[] images, int delay, boolean loop, int prior)
{
sprites = images;
frameLength = delay;
ticksThisFrame = 0;
frameNumber = 0;
isFinished = false;
loops = loop;
priority = prior;
offsets = new Vector2[sprites.length];
}
/**
* Draws the current frame of this Animation at the specified position.
* Also uses the specified scale.
* In addition, advances the animation if appropriate.
*/
public void draw(float x, float y, Vector2 scale, float rotation, boolean flipped)
{
Sprite sprite = ImageManager.getSprite(sprites[frameNumber]);
Vector2 offset = offsets[frameNumber];
int width = (int) (sprite.getWidth()*scale.x);
int height = (int) (sprite.getHeight()*scale.y);
//Draw the current frame at the specified position and size.
if (flipped && offset != null)
sprite.draw((int)((x-offset.x)*scale.x),(int)((y-offset.y)*scale.y),width,height,rotation,flipped);
else
sprite.draw((int)(x*scale.x),(int)((y-offset.y)*scale.y),width,height,rotation,flipped);
}
/**
* Draws the current frame of this Animation at the specified position.
* In addition, advances the animation if appropriate.
*/
public void draw(float x, float y, float width, float height, float rotation, boolean flipped)
{
Sprite sprite = ImageManager.getSprite(sprites[frameNumber]);
Vector2 offset = offsets[frameNumber];
//Draw the current frame at the specified position and size.
if (flipped && offset != null)
sprite.draw((int)(x-offset.x),(int)(y-offset.y),(int)width,(int)height,rotation,flipped);
else
sprite.draw((int)x,(int)(y-offset.y),(int)width,(int)height,rotation,flipped);
}
public void advanceAnimation(float delta)
{
//Advance the frame if appropriate.
ticksThisFrame += delta / Model.TARGET_DELTA;
if (ticksThisFrame >= frameLength)
{
frameNumber++;
ticksThisFrame = 0;
}
if (frameNumber >= sprites.length)
{
if (loops)
frameNumber = 0;
else
frameNumber = sprites.length-1;
isFinished = true;
}
}
public void restart()
{
frameNumber = 0;
isFinished = false;
ticksThisFrame = 0;
}
/**
* Whether or not this animation has reached and finished its last frame.
* @return True / false if it's finished.
*/
public boolean isFinished()
{
return isFinished;
}
public int getPriority()
{
return priority;
}
public boolean loops()
{
return loops;
}
public int getFrameNumber()
{
return frameNumber;
}
public void preloadAll()
{
for (int i = 0; i < sprites.length; i++)
ImageManager.preloadSprite(sprites[i]);
}
/**
* Will calculate image offsets that should be used when it is flipped in order to make
* the animation look fluid. This must be called by whoever has the AnimationSet after
* preloadAll() (or the dependent images have been preloaded), and is therefore not
* automatically called.
*/
public void findOffsets()
{
//Find the smallest sprite (in both width and height).
int minWidth = ImageManager.getSprite(sprites[0]).getWidth();
int minHeight = ImageManager.getSprite(sprites[0]).getHeight();
for (int i = 1; i < sprites.length; i++)
{
int wi = ImageManager.getSprite(sprites[i]).getWidth();
int hi = ImageManager.getSprite(sprites[i]).getHeight();
if (wi < minWidth)
minWidth = wi;
if (hi < minHeight)
minHeight = hi;
}
//Now that we've got the smallest sprite in the animation,
//adjust the offsets of the bigger sprites to match the difference.
for (int i = 0; i < sprites.length; i++)
{
int wi = ImageManager.getSprite(sprites[i]).getWidth();
int hi = ImageManager.getSprite(sprites[i]).getHeight();
offsets[i] = new Vector2(wi-minWidth,hi-minHeight);
}
}
public void manuallySetOffset(int position, Vector2 offset)
{
if (position >= 0 && position < offsets.length)
offsets[position] = offset;
}
public float getTime()
{
return frameNumber * frameLength + ticksThisFrame;
}
public int getLength()
{
return frameLength * sprites.length;
}
}