我有一个关于良好做法的问题。我正在做一个简单的游戏,我正在搞乱一些精灵。
我有一个精灵类。在该类中,有一个每隔几毫秒运行一次的计时器。
现在,我有一个List<Creatures>
和“生物”的每个人,都有一个Sprite对象来运行动画。所以这意味着每个生物都有一个同样的东西。
我决定更改它,并制作一个只在列表上迭代的计时器,并调用为每个“Creature”创建动画的函数。
什么是好习惯?
答案 0 :(得分:5)
如果它们都以相同的间隔运行,那么一个大计时器肯定是要走的路。
即使它们以不同的间隔运行,一个大的计时器(用逻辑确定哪些子处理程序触发)通常仍然是最好的。
某些库将在内部添加此逻辑,并且仅从OS请求单个计时器。你还没有确切地说你正在使用哪个计时器(.NET至少有四个),所以我建议你自己使用一个集中计时器。
答案 1 :(得分:5)
我有一个精灵类。在该类中,有一个每隔几毫秒运行一次的计时器。
不幸的是,它实际上并不存在。您受到(非高性能)系统时钟的分辨率的限制,该时钟约为15 ms。因此,如果您愿意,可以将间隔设置为1,但这不是您实际获得的间隔。
回到主题,对于游戏,一切都应该在同一个时钟上运行。对于每个刻度,你将有一个循环,它更新游戏的逻辑状态(位置和诸如此类),然后是显示(动画帧,blit到屏幕等)。如果你将它们放在不同的计时器上,你可能会遇到问题,因为当它们并行更新时协调对象的状态变得非常困难。
还要意识到您需要规范化更新速率,以确保事情不会更快或太慢(取决于渲染帧所需的时间)。您需要检查上次更新和新更新之间的差异并采取相应措施。
答案 2 :(得分:1)
你最好的选择是实现一个游戏循环,它跟踪自上次循环迭代以来经过了多长时间,然后将经过的时间量传递给需要自我更新的所有实体。 / p>
例如,OpenTk实现了每次通过游戏循环时发生的several events(例如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;
}
}
根据经过的时间,您可以找出要在精灵中渲染的动画帧。
额外的优势在于,通过查看此时间过去,您可以计算出当前运行的每秒帧数并根据它做出决策(跳过帧的渲染,降低渲染复杂性等)。