2D Sprite animation (2D 精灵动画)

简介

在本教程中,你会学到创建二维动画角色的两种不同方法。通常,当你创建或下载动画化的角色时,它将以两种方式出现:作为单独的图像或一个包含所有动画帧的单张sprite sheet(sprite 清单)。根据你拥有的资源类型,可以选择以下解决方案之一。

首先,我们将使用 AnimatedSprite 以及 Sprite 的*Animation(动画)*属性。

注解

以下示例的美术素材由https://opengameart.org/users/ansimuz提供

各自独立的图像与AnimatedSprite (动画化精灵)

在这个情况下,你有一组图像,每一个都包含你角色的动画的一帧。对于这个例子,我们将使用以下动画:

../../_images/2d_animation_run_preview.gif

你可以在此处下载此示例项目: 2D_movement_demo.zip

解压缩这些图像并将它们放在项目文件夹中。使用以下节点布置场景树:

../../_images/2d_animation_tree1.png

注解

根节点也可以是 Area2DRigidBody2D 。动画仍然会以同样的方式制作。一旦动画完成,你可以为CollisionShape2D形状分配一个形状。更多信息请参见 Physics Introduction

现在选择``AnimatedSprite``,并在它的 SpriteFrames(精灵帧) 属性中,选择“新建 SpriteFrames”。

../../_images/2d_animation_new_spriteframes.png

点击新的 SpriteFrames 资源,你会看到一个新的面板出现在编辑器窗口的底部:

../../_images/2d_animation_spriteframes.png

从左边的文件系统面板,将这8张独立的图片拖放到SpriteFrames(精灵帧)面板的中间部分。在左边,将动画名称从“默认”更改为“奔跑”。

../../_images/2d_animation_spriteframes_done.png

回到属性面板,在 Playing(播放) 属性的复选框里打勾。您现在应该可以看到在视区中播放的动画。然而,它有点慢。为了解决这个问题,更改SpriteFrames面板中的 速度 (FPS) 为10。

你可以通过点击“新建动画”按钮并添加其他的图像,来添其他的动画。

控制动画

动画完成后,你可以通过代码中的 play()stop() 方法控制动画。这里有一个简单的例子, 按住右方向键播放动画,松开后就停下。

extends KinematicBody2D

func _process(delta):
    if Input.is_action_pressed("ui_right"):
        $AnimatedSprite.play("run")
    else:
        $AnimatedSprite.stop()

Sprite sheet (精灵清单)和 AnimationPlayer(动画播放器)

如果你有一个包含所有动画帧的sprite sheet,你不能轻易使用``AnimatedSprite``。相反,您可以使用一个基础的: :ref:`Sprite <class_Sprite>`节点来显示纹理,然后用 :ref:`AnimationPlayer <class_AnimationPlayer>`对纹理之间的变化进行动画化。

考虑一下这个sprite sheet,包含6帧动画:

../../_images/2d_animation_player-run.png

右键单击图片,选择“图片另存为”下载图片,然后将图片复制到项目文件夹中。

我们的目的是,循环着一个接一个地显示这些图像。首先布置你的场景树:

../../_images/2d_animation_tree2.png

注解

根节点也可以是 Area2DRigidBody2D 。动画仍然会以同样的方式制作。一旦动画完成,你可以为CollisionShape2D形状分配一个形状。更多信息请参见 Physics Introduction

将sprite sheet拖拽到Sprite的 Texture 属性里,你会看到整个清单显示在屏幕上。要把它分割成单独的帧,在属性面板中展开 Animation 部分,将 Hframes 设置为``6``。Hframes*Vframes*是sprite sheet中水平和垂直帧的数量。

../../_images/2d_animation_setframes.png

现在尝试更改 Frame 属性的值。你可以看到它的范围从``0`` 到 5,Sprite 所显示的图像也随之改变。这就是我们想要动画化的属性。

选中 AnimationPlayer ,然后点击 “动画” 按钮,然后点击“新建”按钮。将新动画命名为“walk”。将动画长度设置为``0.6``,点击 “Loop” 按钮,让动画重复播放。

../../_images/2d_animation_new_animation.png

现在选中``Sprite``节点,并单击钥匙图标,添加一个新的动画轨道(track)。

../../_images/2d_animation_new_track.png

继续在时间轴的每一点添加帧(默认为``0.1``秒),直到你得到了从0到5的所有帧。你会看到这些帧出现在动画轨道(animation track)上:

../../_images/2d_animation_full_animation.png

按下动画上的“播放”键,看看效果如何。

../../_images/2d_animation_running.gif

控制AnimationPlayer动画

正如AnimationSprite一样,你可以通过代码中的``play()`` 和 ``stop()``方法控制动画。同样, 这里有一个简单的例子, 按住右方向键键播放动画,松开后就停下。

extends KinematicBody2D

func _process(delta):
    if Input.is_action_pressed("ui_right"):
        $AnimationPlayer.play("walk")
    else:
        $AnimationPlayer.stop()

注解

如果同时更新一个动画和一个其他的属性(比如说, 一个平台跳跃游戏可能会更新sprite的``h_flip``/v_flip``属性然后同时开始一个"转身"动画), 要记住``play()``不是即时生效的。它是在下次 :ref:`AnimationPlayer <class_AnimationPlayer>` 被处理时生效的。这可能要到下一帧, 导致现在这一帧变成"错误"帧-应用了属性的变化, 但动画还没有开始。如果这会造成麻烦的话, 在调用``play()``后, 你可以调用``advance(0) 来立即开始播放动画。

总结

这些例子展示了在二维动画中最常见的两种情况。每种方法都有其好处。使用 AnimationPlayer 有点复杂,但是提供了额外的功能,因为你也可以为其他像位置或大小这样的属性做动画,如位置或比例。试验一下,看看哪种最适合你的需要。