LibGDX 游戏开发 之 2D动画

原文链接:https://github.com/libgdx/libgdx/wiki/2D-Animation
译者:重庆好爸爸 [email protected]
谢绝转载

概述

2D动画是一种使用静态图片来创建动态效果的技术。这篇文章描述了如何利用libGDX的Animation类来创建动画。
动画是由按照设置的时间间隔和和一定顺序显示的多个帧。比如可以通过拍摄人跑步时的多张照片,然后在循环播放这些照片来实现这个人跑步的动画。
下面的“sprite sheet”图展示了一个人跑步的完整周期。每个框包含一个静态画面。当这些画面在一段时间内顺序显示时,它们将形成动画。

LibGDX 游戏开发 之 2D动画_第1张图片

帧率表示每秒显示的画面数量。上面的例子中,整个跑步周期共有30帧画面。如果角色在1秒中内完成整个跑步周期,那么这30帧画面需要在1秒钟之内全部显示完,这中情况下帧率就是 30 FPS。每帧的时间(称为帧时间或间隔时间)是FPS的倒数,在这种情况下为每帧0.033秒

animation是一个非常简单的状态机。在例子中跑步的人一共有30个状态。编号的帧表示跑步的人经历的状态,一个时间只能存在一个状态。当前是何种状态取决于动画开始后到当前经历的时间。如果少于0.033秒,我们在状态1,所以第一个sprite被绘制。 如果我们在0.033和0.067秒之间,那么我们在状态2,依此类推。 如果动画循环,则在显示所有帧后返回到第一帧。


LibGDX 游戏开发 之 2D动画_第2张图片

Animation类 The Animation class

LibGDX's Animation (code) 类可以用来方便的管理动画。Animation类通过一系列图片和帧间隔来创建动画。在动画播放的时候,getKeyFrame()方法可以通过一个elapsed time参数得到相应的图像。
Animation有一个泛型参数,用来表示图像的类型。 典型的类型是TextureRegion 或者 PolygonRegion, 但是任何renderable 对象都是可以的。该类型通过在动画声明中,指定动画类型来声明,比如:

Animation myAnimation = new Animation(/*...*/)

请注意,使用Sprite类来表示动画的帧通常是不合适的,因为Sprite类包含的位置数据不是从帧到帧的(because the Sprite class contains positional data that would not carry from frame to frame.)。

TextureAtlas 例子

LibGDX's TextureAtlas (code) 类
通常用于将许多单独的纹理区域组合成较小的纹理集合,以减少昂贵的绘图调用 (details here).
TexturePacker和TextureAtlas提供了一种方便的方法来生成动画。 动画的所有源图像应以最后的下划线和帧号命名,如running_0.png, running_1.png, running_2.png, etc. TexturePacker 会自动使用这些号码来作为帧的编号(要求打包参数: use-Indexes 为 true)。
加载TextureAtlas之后,可以立即获取完整的帧数组,并将其传递到Animation构造函数中:

public Animation runningAnimation;
//...
runningAnimation = new Animation(0.033f, atlas.findRegions("running"), PlayMode.LOOP);

Sprite sheet example

以下代码片段将使用animation_sheet.png sprite-sheet创建一个动画,并将动画渲染到屏幕。

public class Animator implements ApplicationListener {

    // Constant rows and columns of the sprite sheet
    private static final int FRAME_COLS = 6, FRAME_ROWS = 5;

    // Objects used
    Animation walkAnimation; // Must declare frame type (TextureRegion)
    Texture walkSheet;
    SpriteBatch spriteBatch;

    // A variable for tracking elapsed time for the animation
    float stateTime;

    @Override
    public void create() {

        // Load the sprite sheet as a Texture
        walkSheet = new Texture(Gdx.files.internal("animation_sheet.png"));

        // Use the split utility method to create a 2D array of TextureRegions. This is 
        // possible because this sprite sheet contains frames of equal size and they are 
        // all aligned.
        TextureRegion[][] tmp = TextureRegion.split(walkSheet, 
                walkSheet.getWidth() / FRAME_COLS,
                walkSheet.getHeight() / FRAME_ROWS);

        // Place the regions into a 1D array in the correct order, starting from the top 
        // left, going across first. The Animation constructor requires a 1D array.
        TextureRegion[] walkFrames = 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++) {
                walkFrames[index++] = tmp[i][j];
            }
        }

        // Initialize the Animation with the frame interval and array of frames
        walkAnimation = new Animation(0.025f, walkFrames);

        // Instantiate a SpriteBatch for drawing and reset the elapsed animation
        // time to 0
        spriteBatch = new SpriteBatch();
        stateTime = 0f;
    }

    @Override
    public void render() {
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
        stateTime += Gdx.graphics.getDeltaTime(); // Accumulate elapsed animation time
        
        // Get current frame of animation for the current stateTime
        TextureRegion currentFrame = walkAnimation.getKeyFrame(stateTime, true);
        spriteBatch.begin();
        spriteBatch.draw(currentFrame, 50, 50); // Draw current frame at (50, 50)
        spriteBatch.end();
    }

    @Override
    public void dispose() { // SpriteBatches and Textures must always be disposed
        spriteBatch.dispose();
        walkSheet.dispose();
    }
}
LibGDX 游戏开发 之 2D动画_第3张图片

使用以下构造函数创建动画非常简单。

Method signature Description
Animation (float frameDuration, TextureRegion... keyFrames) The first parameter is the frame time and the second is an array of regions (frames) making up the animation

Best practices

  • 将帧与其他sprites一起打包成一个纹理,可以优化渲染。 这很容易用TexturePacker完成。
  • 根据游戏类型确定合理数量的帧。 对于复古的街机风格,10 fps可能就足够了,而更逼真的运动需要更多的帧。

Asset

获取 sprite-sheet 这里.

你可能感兴趣的:(LibGDX 游戏开发 之 2D动画)