Animations of Libgdx
A good game always requires Animation. Libgdx provides the Animation class to manage and control animations.
Animation: stores a group of TextureRegion and plays it in sequence. For example, you need to use Animation when the main character is running or jumping. Each TextureRegion is a frame, and multiple frames constitute a group of animations.
Brief description of Animation
The above two images are from the official wiki. Each red box represents this animation and represents a running process of a role. We will use the split method in TextureRegion to cut the image.
There is a parameter in AnimationFrameDurationThis indicates the display time of each frame on the screen. 1/frameDuration is the frame rate, that is, the number of images displayed in one second.
NORMAL playing mode of Animationd: Needless to say, it is NORMAL playing mode. REVERSED. LOOP: continuous playback, which is commonly used. LOOP_REVERSED: continuous playback. LOOP_PINGPONG: play several pictures forward, and then play several frames backward.
Note that only one of the default initialization methods is to initialize the playing mode, and the other is PlayMode. NORMAL by default. In this case, you can use the setPlayMode method or specify public TextureRegion getKeyFrame (float stateTime, boolean looping) when obtaining the key frame. If this parameter is set to true, set PlayMode. LOOP.StateTime description
This stateTime has been set in many sample codes. Now let's talk about my understanding. stateTime is a time counter and is initializedStateTime = 0
/** 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; }
You can use the source code to specify the stateTime to calculate the number of FPS records from which the animation starts to be played. The next frame of animation should be displayed.
The following is the test code.
Private static final String TAG = AnimationTest. class. getSimpleName (); private static final int FRAME_COLS = 6; // there are 6*5 private static final int FRAME_ROWS = 5; // #2 Animation walkAnimation; // defines the Animation object, used to load TextureRegion Animation; Texture animated sheet; // loads 6*5 image TextureRegion [] animated frames; SpriteBatch spriteBatch; TextureRegion currentFrame; // records key frames, that is, the current TextureRegion Vector2 postion; Direction direction; float stateTime; // records the animation time @ Override public void create () {sheet = new Texture (Gdx. files. internal ("sprite-animation1.png"); // #9 TextureRegion [] [] tmp = TextureRegion. split (partition sheet, partition sheet. getWidth ()/FRAME_COLS, Sheet sheet. getHeight ()/FRAME_ROWS); // #10 bytes frames = new TextureRegion [FRAME_COLS * FRAME_ROWS]; int index = 0; for (int I = 0; I <FRAME_ROWS; I ++) {for (int j = 0; j <FRAME_COLS; j ++) {partition frames [index ++] = tmp [I] [j];} walkAnimation = new Animation (0.025f, FIG); // #11 spriteBatch = new SpriteBatch (); // #12 postion = new Vector2 (50, 50); direction = Direction. RIGHT; stateTime = 0f; // #13 Gdx. app. log (TAG, "frameDuration =" + walkAnimation. getFrameDuration (); Gdx. app. log (TAG, "frameDuration =" + walkAnimation. getAnimationDuration ();} @ Override public void render () {Gdx. gl. glClearColor (0.39f, 0.58f, 0.92f, 1.0f); Gdx. gl. glClear (gl1_gl _ COLOR_BUFFER_BIT); // #14 stateTime + = Gdx. graphics. getDeltaTime (); // #15 if (direction = Direction. RIGHT) {postion. x + = 50 * Gdx. graphics. getDeltaTime (); walkAnimation. setPlayMode (PlayMode. LOOP);} else if (direction = Direction. LEFT) {postion. x-= 50 * Gdx. graphics. getDeltaTime (); walkAnimation. setPlayMode (PlayMode. REVERSED);} if (postion. x + repeated frames [0]. getRegionWidth ()> Gdx. graphics. getWidth ()-50) {direction = Direction. LEFT;} else if (postion. x <50) {direction = Direction. RIGHT;} currentFrame = walkAnimation. getKeyFrame (stateTime, true); // #16 spriteBatch. begin (); spriteBatch. draw (currentFrame, postion. x, postion. y); // #17 spriteBatch. end () ;}@ Override public void dispose () {partition sheet. dispose ();} enum Direction {LEFT, RIGHT}
Animation is hard to display. You can run it yourself. Below is the log output
AnimationTest: FIG = 0.025
AnimationTest: FIG = 0.75