1

我有一个关于良好实践的问题。我正在制作一个简单的游戏,并且正在玩弄一些精灵。

我有一个精灵类。在该类中,有一个每隔几毫秒运行一次的计时器。

现在,我有一个List<Creatures>和每个人的“生物”,在其中有一个 Sprite 对象来运行动画。所以这意味着每个生物都有一个做同样事情的计时器。

我决定改变这一点,制作一个只在列表上迭代的计时器,并调用为每个“生物”创建动画的函数。

什么是好的做法?

  1. 给每个“生物”自己的计时器。
  2. 在表单中创建一个迭代列表的“大”计时器,并调用从每个对象创建动画的函数。
  3. 不一样的方式
4

3 回答 3

5

如果它们都以相同的间隔运行,那么一个大计时器绝对是要走的路。

即使它们以不同的间隔运行,一个大计时器(通过逻辑确定哪个子处理程序触发)通常仍然是最好的。

一些库会在内部添加这个逻辑,并且只向操作系统请求一个计时器。您还没有确切说明您正在使用哪个计时器(.NET 至少有四个),所以我建议您自己使用一个集中式计时器。

于 2012-04-10T21:15:48.163 回答
5

我有一个精灵类。在该类中,有一个每隔几毫秒运行一次的计时器。

不幸的是,事实并非如此。您受到(非高性能)系统时钟分辨率的限制,大约为 15 毫秒。因此,您可以根据需要将间隔设置为 1,但这并不是您实际得到的。

回到主题,对于游戏来说,一切都应该在同一个时钟上运行。对于每个刻度,您将有一个循环更新游戏的逻辑状态(位置和诸如此类),然后是显示(动画帧、blit 到屏幕等)。如果您将它们放在不同的计时器上,您可能会遇到问题,因为在并行更新对象时协调对象的状态将变得非常困难。

还要意识到您需要标准化更新速率,以确保更新不会太快或太慢(取决于渲染帧所需的时间)。您需要检查上次更新和新更新之间的增量并采取相应措施。

于 2012-04-10T21:16:08.420 回答
1

最好的办法是实现一个游戏循环,该循环跟踪自上次循环迭代以来经过了多少时间,然后将经过的时间量传递给所有需要自我更新的实体。

例如,OpenTk实现了在每次通过游戏循环时发生的几个事件(例如 OnUpdateFrame、OnRenderFrame)。

这些事件中的每一个都传递了一个FrameEventArgs类型的参数,该参数具有一个 Time 属性:

/// <summary>
/// Gets a <see cref="System.Double"/> that indicates how many seconds of time elapsed since the previous event.
/// </summary>
public double Time 
{
    get { return elapsed; }
    internal set
    {
        if (value <= 0)
            throw new ArgumentOutOfRangeException();
        elapsed = value;
    }
}

根据经过的时间,您可以确定要在精灵中渲染的动画帧。

额外的好处是,通过查看这段时间,您可以计算出您当前正在运行的每秒帧数并根据它做出决策(跳过帧的渲染,降低渲染复杂性等)。

于 2012-04-10T21:26:07.797 回答