Answers:
从根本上讲,您处在正确的轨道上-您需要知道动画可以持续多长时间来执行此类操作。动画不仅仅是帧的集合,您还需要围绕它们的各种其他信息。例如,那里有几帧,动画会循环播放,它会播放多快(例如,每秒10动画帧或25或60动画帧?)。可以根据一些数据来定义每个动画,一些通用的动画代码可以查看并回放这些数据。您应该将动画部分封装在自己的代码中,该代码除了这些动画定义以及如何显示单个图像帧外什么都不知道。也就是说,有一个动画对象,您可以在屏幕上的特定位置加载,开始播放,停止播放以及告诉渲染。
一种灵活的方法是使用一种动画定义来封装这种信息。因此,与其说“动画X是所有这些帧,而是通过它们播放”,不如说有点复杂。
例如,具有某种模拟的数据格式
动画= { {name =“ walk”,files =“ walk * .png”,frameCount =“ 12”,loop =“ true”}, {name =“ fire” files =“ fire * .png” frameCount =“ 6”, 事件= { {name =“ bulletLeavesGun”,frame =“ 4”,param1 =“ 43”,param2 =“ 30”} } } }
因此,您的代码显示如下内容:
currentAnimation = animations.Get("fire");
currentAnimation.Play();
您可以通过动画代码回叫您(例如,由于动画已播放到特定帧而检测到新事件时,它会调用您的游戏代码来告知新事件)来检测事件,或者通过轮询动画如下:
List<Event> events = currentAnimation.EventsSinceLastCheck();
foreach (AnimationEvent event in events)
{
if (event.name == "bulletLeavesGun")
{
Vector2 bulletPosition = new Vector2(event.param1, event.param2);
Vector2 actualBulletPosition = new Vector2(
character.x + bulletPosition.x,
character.y + bulletPosition.y);
CreateBulletAt(actualBulletPosition);
}
}
注意事项:
如果您不需要在动画中进行子弹发射,而只需完成一次,就可以在没有事件概念的情况下使用复杂得多的系统。但是,您仍然需要一个动画可以自己播放,知道它们有多长时间并且可以在动画完成时回调游戏代码的系统。
以某种方式,您必须等到动画完成后再在该点创建项目符号。
如果您确定动画速率是固定的,则只需设置一个计时器即可。作为一个较小的变体,您可以在项目符号内部添加代码,使其在出现和移动之前隐式等待一会儿。
根据您的开发平台,您可能具有某种动画更新功能或回调,可以让您在动画到达所需点的确切时间进行响应。例如,这就是我使用Flixel的方式。
addAnimationCallback
方法可用于触发实体。在回调函数中,您可以查看射击动画的当前帧是否为应创建项目符号实体的帧。如果是,则可以在屏幕上添加项目符号。
直截了当的答案:假设您有一个要在播放器按下“开火”按钮时播放的动画,然后在播放完毕后弹出子弹。理想情况下,您应该避免对动画时间进行硬编码,并在动画完成时触发子弹(使用回调函数或其他方法,具体取决于您的平台)。我想不出其他任何不太复杂的方法。
替代游戏设计的答案:除非有确凿的充分理由,否则我将避免因按下“开火”按钮而让子弹出现而延迟。除非动画真的非常短(最大一两个帧,基本上是一个枪口的闪光),否则它将使触发按钮的响应变慢,并且只会使典型的玩家感到烦恼。即使您确实决定在子弹出来之前使用动画(基于回合的RPG和战术游戏也是这样做的可接受的理由),我仍会考虑在某处包括“关闭动画”选项,以允许如果玩家愿意,游戏可以更快地移动。
首先,我将使用事件系统(观察者模式?)来解耦代码段。这不仅用于动画,而且肯定适用于此。然后,动画代码可以简单地说出dispatchEvent(event),而代码的其他部分侦听该事件,而代码的任何一部分都不需要彼此了解。
现在,动画代码实际上需要引用事件分配器(通过依赖注入轻松完成),并且您需要具有一些XML或JSON,它们实际上定义了动画。就像是:
{
animation: {
name: shoot,
length: 12,
spritesheet: shoot.png
event: {
frame: 4,
name: bulletLeavesGun,
},
},
}
加载动画时读入数据,并让动画代码在回放过程中将事件分发到该帧时调度该事件。