Subversion Repositories AndroidProjects

Rev

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);
        }
       
}