Sprite动画最佳做法


18

我想更好地了解现实世界中人们如何处理动画。

您是否加载1张大图像,然后根据动画帧绘制不同的矩形?

是否将X图像文件加载到数组中并根据动画帧在数组中绘制项目?

如何处理具有不同长度的各种精灵的动画。

假设角色行走需要4到8帧,而沙滩上的波浪只需要2-3帧。您将如何处理这种情况?见下文

Dim Waves(1) as Sprite
Dim Char(5) as Sprite

Sub Animate()
     Frame += 1
     Draw Char(Frame)
     Draw Waves(Frame)
     If Frame = 5 Then Frame = 0
End Sub

显然,Waves最终会出现超出范围的错误。

还是让Sprite担心它自己的动画,而根本不关心帧。让每个精灵知道自己的动画循环吗?

Answers:


23

我过去做的方法是将动画数据动画回放分开。一Animation则可以成为基本的数组Frames和一些属性描述动画应该如何表现(如果循环等)。

我通常加载一张图像并将其绘制。

每个Frame动画本质上都是一个矩形和一段时间。这允许某些帧显示的时间比其他帧显示的时间长,这可能是您想要的,也可能不是。如果希望动画中的所有帧都显示相同的时间,请将其存储在Animation对象中。

任何需要播放动画的东西都有它自己的AnimationPlayer,可以指向动画Animation。播放器对象负责播放动画,并使“当前帧”可用。

对我来说,这样做的好处是我可以有一个Animation对象的单个实例,许多对象可以指向该实例,并同时扮演不同的角色。只需将动画指向AnimationPlayer另一个Animation对象并重置播放,即可轻松更改动画。

编辑这是上述系统的相当基本的JavaScript实现。我在几分钟内把它放在一起作为演示。“真实”代码将具有更多功能。不过,您需要一个同时支持Canvas和Data URI的现代浏览器才能正常工作。


1
他说什么。此外,动画中每个帧都有一个x / y偏移量通常很方便,这样您就可以将精灵图像紧紧地包装到其边框中,然后将它们放置在动画中所需的位置。它还可以让您仅使用单个图像就可以完成诸如抖动之类的一些基本操作。
优厚

是的,我完全同意。实际上,我使用的动画系统允许这样做。无需编辑图像数据,即可更轻松地更改任何帧的位置。
Zack The Human

很好的工作示例,WOW竖起大拇指。会推荐的。
DFectuoso

动画种类的一个重要限制是,不能从不同的角度观看人物形象-远离观察者,走向观察者等。或者我错了吗?
Majid Fouladpour 2013年

@MajidFouladpour我认为使用这种技术不存在这种限制。对于每个“视角”,您仅具有不同的AnimationData对象。
Zack The Human

1

我会让一个动画知道它有多少帧。除了性能问题外,它们的存储位置和方式相对无关紧要(例如,您可能希望它们具有相同的纹理)。我不会将1加到帧数中,我会添加deltaTime * animSpeed并在显示时将该值转换为整数。这样,您可以放慢或加快动画的播放速度,并且与帧速率无关。

因此,子画面将具有可自我更新的动画。


0

为什么不为每个对象存储一定数量的帧?我个人将动画中的帧数传递给构造函数中的对象,然后有一个标准的Animate()函数接收动画中的帧数。


0

这取决于实现方式。在引擎中,我同时在Direct3D和DirectDraw中制作动画。

在DirectDraw中,我创建一个大图像。无论如何,所有这些都存储在系统内存中,最终归结为一维数据块。

优点:

  • 容易在框架之间移动。更改开始指针,每隔y添加间距(总图像宽度),您就很高兴了。

缺点:

  • 不能只复制一帧到屏幕,而是必须手动进行。

  • 巨大的内存块。匆忙忙忙地取景需要付出代价。

在Direct3D中,我使用单独的纹理。这是因为我不知道设备的纹理限制,所以我不知道它是否支持整个图像大小的纹理。

优点:

  • 您可以将框架直接复制到屏幕上,因为它们都是单独的实体。

缺点:

  • 缺少内存对齐。

0

我的游戏中,我为Sprite基类提供了有关如何绘制自身的知识,所有动画元素都继承了该知识:动画帧的数量和持续时间,屏幕上的位置等。主游戏循环仅遍历所有对象精灵,要求每个精灵自己绘制自己认为合适的对象。似乎工作得很好,并且更具模块化:如果您添加一个具有不同动画循环(甚至更复杂:多个动画状态)的新精灵,则无需返回并重写Animate ()例程以容纳额外的复杂性:

Dim Waves as Sprite
Dim Char as Sprite

Sub Animate()
     Char.update()
     Waves.update()
End Sub

每次调用一个sprite的update()方法时,它都会知道是否应重画与上次相同的帧,移至当前动画中的下一帧,更改为新动画等。

这样做的另一个好处是,可以更轻松地调整帧速率以适应不同的时钟/平台渲染速度,因为唯一的变化就是调用Animate()的频率。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.