add TextureAtlasAnimator

This commit is contained in:
Gered 2013-07-20 11:14:20 -04:00
parent bb516baa2f
commit aff54c9c1d
2 changed files with 182 additions and 0 deletions

View file

@ -0,0 +1,33 @@
package com.blarg.gdx.graphics.atlas;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.Disposable;
class AnimationSequence implements Disposable {
public TextureAtlas atlas;
public int animatingIndex;
public int start;
public int stop;
public int current;
public float delay;
public float currentFrameTime;
public boolean isAnimating;
public boolean loop;
public Pixmap originalAnimatingTile;
public Pixmap[] frames;
public int getNumFrames() {
return stop - start + 1;
}
public boolean isAnimationFinished() {
return (isAnimating && !loop && current == stop);
}
@Override
public void dispose() {
originalAnimatingTile.dispose();
for (int i = 0; i < frames.length; ++i)
frames[i].dispose();
}
}

View file

@ -0,0 +1,149 @@
package com.blarg.gdx.graphics.atlas;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.TextureData;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.ObjectMap;
import com.blarg.gdx.graphics.GraphicsHelpers;
public class TextureAtlasAnimator implements Disposable {
ObjectMap<String, AnimationSequence> animations;
public TextureAtlasAnimator() {
animations = new ObjectMap<String, AnimationSequence>();
}
public void addSequence(String name, TextureAtlas atlas, int tileToBeAnimated, int start, int stop, float delay, boolean loop) {
if (animations.containsKey(name))
throw new UnsupportedOperationException("Duplicate animation sequence name.");
if (atlas.texture.getTextureData().getType() != TextureData.TextureDataType.Pixmap)
throw new UnsupportedOperationException("This only works with Textures backed by Pixmap texture data.");
AnimationSequence sequence = new AnimationSequence();
sequence.atlas = atlas;
sequence.animatingIndex = tileToBeAnimated;
sequence.start = start;
sequence.stop = stop;
sequence.delay = delay;
sequence.isAnimating = true;
sequence.loop = loop;
sequence.frames = new Pixmap[sequence.getNumFrames()];
sequence.current = sequence.start;
sequence.currentFrameTime = 0.0f;
// build up some CPU-side cache's of image data from the original TextureAtlas texture. we grab the image data
// for the tile we're placing animation frames to so we can restore the original texture when/if needed. and we
// grab each of the tiles that appear in the animation sequence so we can quickly upload it to the texture when
// we're at that frame
// grab the TextureAtlas texture's image data
TextureData textureData = atlas.texture.getTextureData();
if (!textureData.isPrepared())
textureData.prepare();
Pixmap textureImage = textureData.consumePixmap();
// copy the image data for the destination animation tile region
TextureRegion tileRegion = atlas.get(tileToBeAnimated);
sequence.originalAnimatingTile = new Pixmap(tileRegion.getRegionWidth(), tileRegion.getRegionHeight(), textureData.getFormat());
sequence.originalAnimatingTile.drawPixmap(
textureImage, 0, 0,
tileRegion.getRegionX(), tileRegion.getRegionY(), tileRegion.getRegionWidth(), tileRegion.getRegionHeight()
);
// copy image data for each of the animation sequence tiles (from "start" to and including "stop")
for (int i = 0; i < sequence.getNumFrames(); ++i) {
TextureRegion tile = atlas.get(i + sequence.start);
sequence.frames[i] = new Pixmap(tileRegion.getRegionWidth(), tileRegion.getRegionHeight(), textureData.getFormat());
sequence.frames[i].drawPixmap(
textureImage, 0, 0,
tile.getRegionX(), tile.getRegionY(), tile.getRegionWidth(), tile.getRegionHeight()
);
}
// all good!
animations.put(name, sequence);
}
public void resetSequence(String name) {
AnimationSequence sequence = animations.get(name);
if (sequence == null)
throw new RuntimeException("No sequence with that name.");
sequence.isAnimating = true;
sequence.current = sequence.start;
sequence.currentFrameTime = 0.0f;
updateTextureWithCurrentTileFrame(sequence);
}
public void stopSequence(String name, boolean restoreOriginalTile) {
AnimationSequence sequence = animations.get(name);
if (sequence == null)
throw new RuntimeException("No sequence with that name.");
sequence.isAnimating = false;
sequence.current = sequence.stop;
sequence.currentFrameTime = 0.0f;
if (restoreOriginalTile)
restoreTextureWithOriginalTile(sequence);
else
updateTextureWithCurrentTileFrame(sequence);
}
public void enableSequence(String name, boolean enable) {
AnimationSequence sequence = animations.get(name);
if (sequence == null)
throw new RuntimeException("No sequence with that name.");
sequence.isAnimating = enable;
sequence.currentFrameTime = 0.0f;
updateTextureWithCurrentTileFrame(sequence);
}
public void onUpdate(float delta) {
for (ObjectMap.Entry<String, AnimationSequence> i : animations.entries()) {
AnimationSequence sequence = i.value;
if (!sequence.isAnimationFinished() && sequence.isAnimating) {
sequence.currentFrameTime += delta;
if (sequence.currentFrameTime >= sequence.delay) {
// move to the next frame
sequence.currentFrameTime = 0.0f;
++sequence.current;
if (sequence.current > sequence.stop)
sequence.current = sequence.start;
updateTextureWithCurrentTileFrame(sequence);
}
}
}
}
public void onResume() {
for (ObjectMap.Entry<String, AnimationSequence> i : animations.entries())
updateTextureWithCurrentTileFrame(i.value);
}
private void updateTextureWithCurrentTileFrame(AnimationSequence sequence) {
int frameIndex = sequence.current - sequence.start;
Pixmap frameImage = sequence.frames[frameIndex];
TextureRegion tile = sequence.atlas.get(sequence.animatingIndex);
GraphicsHelpers.drawToTexture(sequence.atlas.texture, frameImage, tile.getRegionX(), tile.getRegionY());
}
private void restoreTextureWithOriginalTile(AnimationSequence sequence) {
TextureRegion tile = sequence.atlas.get(sequence.animatingIndex);
GraphicsHelpers.drawToTexture(sequence.atlas.texture, sequence.originalAnimatingTile, tile.getRegionX(), tile.getRegionY());
}
@Override
public void dispose() {
for (ObjectMap.Entry<String, AnimationSequence> i : animations.entries()) {
restoreTextureWithOriginalTile(i.value);
i.value.dispose();
}
animations.clear();
}
}