Blame |
Last modification |
View Log
| RSS feed
package com.gebauz.Bauzoid.graphics.sprite;
/** Sprite animation class. */
public class Animation
{
public static final int LOOPED = 0;
/** -1 means infinite loops. */
private int mNumLoops = LOOPED;
private int mPlaybackLoops = 0;
private float mPlaybackPosition = 0.0f;
private float mTotalDuration = 0.0f;
private boolean mIsPlaying = false;
private AnimationFrame[] mFrames = null;
private int mCurrentFrame = -1;
/** Constructor.
* Takes frame definitions and loop behaviour, and preprocesses
* frames for faster access.
* @param frames Frame definitions.
* @param numLoops Number of loops, or LOOPED for infinite loops.
*/
public Animation(AnimationFrame[] frames, int numLoops)
{
mFrames = frames;
mNumLoops = numLoops;
// preprocess frame begin/end times
float pos = 0.0f;
for (AnimationFrame f : mFrames)
{
f.setBeginEnd(pos, pos + f.getDuration());
pos += f.getDuration();
}
mTotalDuration = pos;
mPlaybackLoops = 0;
mCurrentFrame = 0;
}
public void dispose()
{
mFrames = null;
}
/** Start from beginning. */
public void start()
{
start(0.0f);
}
/** Start at specified position. */
public void start(float startAt)
{
mIsPlaying = true;
mCurrentFrame = 0;
mPlaybackPosition = startAt;
mPlaybackLoops = 0;
}
/** Stop and rewind to zero. */
public void stop()
{
mIsPlaying = false;
mPlaybackPosition = 0.0f;
mCurrentFrame = 0;
mPlaybackLoops = mNumLoops;
}
/** Pause and hold current playback position. */
public void pause()
{
mIsPlaying = false;
}
/** Unpause and resume at current playback position. */
public void resume()
{
mIsPlaying = true;
}
/** Set the playback position directly.
* The looping parameters are untouched by this.
*/
public void setPlaybackPosition(float pos)
{
mPlaybackPosition = pos;
}
/** Update animation. */
public void update(float deltaTime)
{
if (!isPlaying())
return;
mPlaybackPosition += deltaTime;
AnimationFrame currentFrame = getCurrentFrame();
if (!currentFrame.isInFrame(mPlaybackPosition))
{
// current frame is not current anymore, so we need to update
if (mPlaybackPosition > currentFrame.getEndTime())
{
// playback position is behind current frame
if (mCurrentFrame >= (mFrames.length - 1))
{
// playback is beyond end point of the animation, so loop if required.
loopAround();
mCurrentFrame = findFrameAt(mPlaybackPosition);
}
else
{
// playback has not reached end of animation yet, so update current frame
// we only need to look at frames after the current one
mCurrentFrame = findFrameAfter(mPlaybackPosition, mCurrentFrame);
}
}
else if (mPlaybackPosition < currentFrame.getBeginTime())
{
// playback position is before current frame
// we only need to look at frames before the current one
mCurrentFrame = findFrameBefore(mPlaybackPosition, mCurrentFrame);
}
}
// if no current frame, use 0
if (mCurrentFrame == -1)
mCurrentFrame = 0;
}
/** Render animation. */
public void render()
{
}
/** Handle looping when playback position is beyond total duration. */
private final void loopAround()
{
while (mPlaybackPosition >= mTotalDuration)
{
mPlaybackLoops++;
if ((mNumLoops == LOOPED) || (mPlaybackLoops < mNumLoops))
{
mPlaybackPosition -= mTotalDuration;
}
else
{
stop();
return;
}
}
}
/** Find the frame that is current according to playback position. */
public final int findFrameAt(float playbackPos)
{
for (int i = 0; i < mFrames.length; i++)
{
AnimationFrame f = mFrames[i];
if (f.isInFrame(playbackPos))
{
return i;
}
}
return -1;
}
/** Find frame at playbackPos after specified index. */
private final int findFrameAfter(float playbackPos, int index)
{
for (int i = index + 1; i < mFrames.length; i++)
{
AnimationFrame f = mFrames[i];
if (f.isInFrame(playbackPos))
{
return i;
}
}
return -1;
}
/** Find frame at playbackPos before specified index. */
private final int findFrameBefore(float playbackPos, int index)
{
for (int i = index - 1; i <= 0; i++)
{
AnimationFrame f = mFrames[i];
if (f.isInFrame(playbackPos))
{
return i;
}
}
return -1;
}
/** Get current frame. */
public final AnimationFrame getCurrentFrame()
{
return mFrames[mCurrentFrame];
}
/** Check if the animation is playing or paused/stopped. */
public final boolean isPlaying()
{
return mIsPlaying;
}
/** Check if the playback has finished.
* Looped animations (with LOOPED parameter) are never finished.
*/
public final boolean isFinished()
{
return (mPlaybackLoops >= mNumLoops);
}
}