Java tutorial
/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.badlogic.gdx.graphics.g2d; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.Array; /** <p> * An Animation stores a list of {@link TextureRegion}s representing an animated sequence, e.g. for running or jumping. Each * region of an Animation is called a key frame, multiple key frames make up the animation. * </p> * * @author mzechner */ public class Animation { /** Defines possible playback modes for an {@link Animation}. */ public enum PlayMode { NORMAL, REVERSED, LOOP, LOOP_REVERSED, LOOP_PINGPONG, LOOP_RANDOM, } final TextureRegion[] keyFrames; private float frameDuration; private float animationDuration; private int lastFrameNumber; private float lastStateTime; private PlayMode playMode = PlayMode.NORMAL; /** Constructor, storing the frame duration and key frames. * * @param frameDuration the time between frames in seconds. * @param keyFrames the {@link TextureRegion}s representing the frames. */ public Animation(float frameDuration, Array<? extends TextureRegion> keyFrames) { this.frameDuration = frameDuration; this.animationDuration = keyFrames.size * frameDuration; this.keyFrames = new TextureRegion[keyFrames.size]; for (int i = 0, n = keyFrames.size; i < n; i++) { this.keyFrames[i] = keyFrames.get(i); } this.playMode = PlayMode.NORMAL; } /** Constructor, storing the frame duration, key frames and play type. * * @param frameDuration the time between frames in seconds. * @param keyFrames the {@link TextureRegion}s representing the frames. * @param playMode the animation playback mode. */ public Animation(float frameDuration, Array<? extends TextureRegion> keyFrames, PlayMode playMode) { this.frameDuration = frameDuration; this.animationDuration = keyFrames.size * frameDuration; this.keyFrames = new TextureRegion[keyFrames.size]; for (int i = 0, n = keyFrames.size; i < n; i++) { this.keyFrames[i] = keyFrames.get(i); } this.playMode = playMode; } /** Constructor, storing the frame duration and key frames. * * @param frameDuration the time between frames in seconds. * @param keyFrames the {@link TextureRegion}s representing the frames. */ public Animation(float frameDuration, TextureRegion... keyFrames) { this.frameDuration = frameDuration; this.animationDuration = keyFrames.length * frameDuration; this.keyFrames = keyFrames; this.playMode = PlayMode.NORMAL; } /** Returns a {@link TextureRegion} based on the so called state time. This is the amount of seconds an object has spent in the * state this Animation instance represents, e.g. running, jumping and so on. The mode specifies whether the animation is * looping or not. * * @param stateTime the time spent in the state represented by this animation. * @param looping whether the animation is looping or not. * @return the TextureRegion representing the frame of animation for the given state time. */ public TextureRegion getKeyFrame(float stateTime, boolean looping) { // we set the play mode by overriding the previous mode based on looping // parameter value PlayMode oldPlayMode = playMode; if (looping && (playMode == PlayMode.NORMAL || playMode == PlayMode.REVERSED)) { if (playMode == PlayMode.NORMAL) playMode = PlayMode.LOOP; else playMode = PlayMode.LOOP_REVERSED; } else if (!looping && !(playMode == PlayMode.NORMAL || playMode == PlayMode.REVERSED)) { if (playMode == PlayMode.LOOP_REVERSED) playMode = PlayMode.REVERSED; else playMode = PlayMode.LOOP; } TextureRegion frame = getKeyFrame(stateTime); playMode = oldPlayMode; return frame; } /** Returns a {@link TextureRegion} based on the so called state time. This is the amount of seconds an object has spent in the * state this Animation instance represents, e.g. running, jumping and so on using the mode specified by * {@link #setPlayMode(PlayMode)} method. * * @param stateTime * @return the TextureRegion representing the frame of animation for the given state time. */ public TextureRegion getKeyFrame(float stateTime) { int frameNumber = getKeyFrameIndex(stateTime); return keyFrames[frameNumber]; } /** Returns the current frame number. * @param stateTime * @return current frame number */ public int getKeyFrameIndex(float stateTime) { if (keyFrames.length == 1) return 0; int frameNumber = (int) (stateTime / frameDuration); switch (playMode) { case NORMAL: frameNumber = Math.min(keyFrames.length - 1, frameNumber); break; case LOOP: frameNumber = frameNumber % keyFrames.length; break; case LOOP_PINGPONG: frameNumber = frameNumber % ((keyFrames.length * 2) - 2); if (frameNumber >= keyFrames.length) frameNumber = keyFrames.length - 2 - (frameNumber - keyFrames.length); break; case LOOP_RANDOM: int lastFrameNumber = (int) ((lastStateTime) / frameDuration); if (lastFrameNumber != frameNumber) { frameNumber = MathUtils.random(keyFrames.length - 1); } else { frameNumber = this.lastFrameNumber; } break; case REVERSED: frameNumber = Math.max(keyFrames.length - frameNumber - 1, 0); break; case LOOP_REVERSED: frameNumber = frameNumber % keyFrames.length; frameNumber = keyFrames.length - frameNumber - 1; break; } lastFrameNumber = frameNumber; lastStateTime = stateTime; return frameNumber; } /** Returns the keyFrames[] array where all the TextureRegions of the animation are stored. * @return keyFrames[] field */ public TextureRegion[] getKeyFrames() { return keyFrames; } /** Returns the animation play mode. */ public PlayMode getPlayMode() { return playMode; } /** Sets the animation play mode. * * @param playMode The animation {@link PlayMode} to use. */ public void setPlayMode(PlayMode playMode) { this.playMode = playMode; } /** Whether the animation would be finished if played without looping (PlayMode#NORMAL), given the state time. * @param stateTime * @return whether the animation is finished. */ public boolean isAnimationFinished(float stateTime) { int frameNumber = (int) (stateTime / frameDuration); return keyFrames.length - 1 < frameNumber; } /** Sets duration a frame will be displayed. * @param frameDuration in seconds */ public void setFrameDuration(float frameDuration) { this.frameDuration = frameDuration; this.animationDuration = keyFrames.length * frameDuration; } /** @return the duration of a frame in seconds */ public float getFrameDuration() { return frameDuration; } /** @return the duration of the entire animation, number of frames times frame duration, in seconds */ public float getAnimationDuration() { return animationDuration; } }