游戏循环和时间跟踪
问题描述:
也许我只是一个白痴,但我一直试图实现一个游戏循环整天,它只是不点击。我从字面上阅读了我在Google上可以找到的每篇文章,但问题是它们都使用不同的计时机制,这使得它们很难应用于我的特定情况(一些使用毫秒,其他使用刻度等)。游戏循环和时间跟踪
基本上,我有一个Clock
对象,每次执行游戏循环时都会更新。
internal class Clock {
public static long Timestamp {
get { return Stopwatch.GetTimestamp(); }
}
public static long Frequency {
get { return Stopwatch.Frequency; }
}
private long _startTime;
private long _lastTime;
private TimeSpan _totalTime;
private TimeSpan _elapsedTime;
/// <summary>
/// The amount of time that has passed since the first step.
/// </summary>
public TimeSpan TotalTime {
get { return _totalTime; }
}
/// <summary>
/// The amount of time that has passed since the last step.
/// </summary>
public TimeSpan ElapsedTime {
get { return _elapsedTime; }
}
public Clock() {
Reset();
}
public void Reset() {
_startTime = Timestamp;
_lastTime = 0;
_totalTime = TimeSpan.Zero;
_elapsedTime = TimeSpan.Zero;
}
public void Tick() {
long currentTime = Timestamp;
if (_lastTime == 0)
_lastTime = currentTime;
_totalTime = TimestampToTimeSpan(currentTime - _startTime);
_elapsedTime = TimestampToTimeSpan(currentTime - _lastTime);
_lastTime = currentTime;
}
public static TimeSpan TimestampToTimeSpan(long timestamp) {
return TimeSpan.FromTicks(
(timestamp * TimeSpan.TicksPerSecond)/Frequency);
}
}
我基于XNA的大部分GameClock
,但它大大简化。然后,我有一个Time
类,它拥有Update
和Draw
方法需要知道的各种时间。
public class Time {
public TimeSpan ElapsedVirtualTime { get; internal set; }
public TimeSpan ElapsedRealTime { get; internal set; }
public TimeSpan TotalVirtualTime { get; internal set; }
public TimeSpan TotalRealTime { get; internal set; }
internal Time() { }
internal Time(TimeSpan elapsedVirtualTime, TimeSpan elapsedRealTime,
TimeSpan totalVirutalTime, TimeSpan totalRealTime) {
ElapsedVirtualTime = elapsedVirtualTime;
ElapsedRealTime = elapsedRealTime;
TotalVirtualTime = totalVirutalTime;
TotalRealTime = totalRealTime;
}
}
我的主类保存了Time
一个实例,它应该在游戏循环过程中不断更新。到目前为止,我有这个:
private static void Loop() {
do {
Clock.Tick();
Time.TotalRealTime = Clock.TotalTime;
Time.ElapsedRealTime = Clock.ElapsedTime;
InternalUpdate(Time);
InternalDraw(Time);
} while (!_exitRequested);
}
时间类的实时属性变得很好。现在我想得到一个适当的更新/绘制循环,以便状态每帧更新一次可变的次数,但是在固定的时间步长。同时,Time.TotalVirtualTime
和Time.ElapsedVirtualTime
应该相应地更新。另外,我打算在未来支持多人游戏,以防对游戏循环的设计产生影响。
有关如何实现此操作的任何提示或示例(除了指向文章的链接)?
答
XNA主要使用的方法是以某种固定速率拨打Update()
,并尽可能多地拨打Draw()
,达到一定限度。在Update()
方法中,您只需更新变量以在新时刻反映世界,当调用Draw()
时,您只能将其绘制到屏幕上。
要获得Update()
以固定的速率运行,您可能希望使用定时器或更准确的计时使用:
[DllImport("kernel32.dll")]
public static extern long GetTickCount();
然后,你可以使用另一个(慢)的计时器,它的调用Invalidate()
用于绘制游戏的对象(画布)。在画布'Paint-event中,您可以拨打Draw()
。这样,每当系统认为有必要(当它使您的画布无效时),或者一旦您有机会这样做,您的世界就会被绘制,一旦您调用Invalidate()
。
对不起,我忘了提及我只关心在Xbox 360上运行,这意味着我将无法访问P/Invoke,并且我不需要担心系统何时需要绘制,因为我可以随时画画。 'Clock'类已经通过使用'Stopwatch.GetTimestamp()'准确计时。我的问题是关于如何构建固定更新循环以及如何跟踪流逝的“游戏/虚拟时间”。我认为我有一个相当好的理解,但我希望有一些建议,以防万一有更好的方法来做到这一点。不过谢谢你的回答! – 2010-04-04 14:50:02