我编写了一个普通的调度程序计时器方法,用于在WPF中创建游戏循环。我注意到,如果将它设置为比200毫秒更短的间隔,它就不能正确赶上。
我将秒打印到屏幕上(参见下面的代码)并将其与我的手表进行比较。设置为500毫秒,没关系,但是如果我把它设置得低得多,就会有很大的差异。我尝试了10毫秒的设置,这意味着屏幕上的时间在(实际)分钟内仅通过38秒! (请注意,我的所有游戏引擎代码在测试期间都被删除了,所以它只是被调用的定时器循环。另外,如果我从VS运行代码或者在Debug中运行exe文件也没关系文件夹)。
请注意,我创建的游戏运行顺畅,只是我的(标准)Every_Tick方法在正确的时间没有被调用。这反过来意味着我的游戏将在更快的计算机上运行得更快。
那么如何保持正确的时间跟踪并确保Every_Tick方法同时触发,与所使用的计算机(或手机)无关?也就是说,我宁愿对游戏对象的数量,碰撞检测精度等进行限制,但要准时,而不是尽可能快地进行。换句话说,如果我将定时器增量值设置为50ms(我认为这是合理的,因为这意味着每秒20次),我真的希望游戏每秒更新20次。
如果有可能避免它,我真的不想进入线程等,因为游戏本身现在运行良好。我只是希望他们以相同的速度回放。
我在How to control frame rate in WPF by using dispatcher timer accurately?查看了一些很棒的回复,但这仍然没有回答我的问题:如何让我的游戏以相同的速度运行,无论(现代)计算机/手机和无论是WPF / UWP还是别的什么?
或者这是不可能以一种相当简单的方式做到的,我应该接受游戏速度取决于所使用的计算机?
谢谢!
代码:
public void StartTimer()
{
//This variable is used to get to the controls (labels etc) of the MainWindow (WPF)
MainWindow mainWin = System.Windows.Application.Current.Windows.Cast<System.Windows.Window>().FirstOrDefault(window => window is MainWindow) as MainWindow;
time = TimeSpan.FromSeconds(0);
//What the code below does is this:
//For each 10 ms, call the different methods. Then add 10 ms to the current time.
timer = new DispatcherTimer(new TimeSpan(0, 0, 0, 0, 10), DispatcherPriority.Normal, delegate
{
if (runGame == false) return; //only go on if not in pause mode
mainWin.txtInfo.Text = time.ToString("mm\\:ss");//Shows the timer in a textbox, only showing minutes and seconds.
//Collision code etc removed during the test
time = time.Add(TimeSpan.FromMilliseconds(10)); //adds a specified time to the current time
}, System.Windows.Application.Current.Dispatcher);
}
请注意,上面的代码是为了测试目的而添加的。原始代码(面临同样的问题)看起来像这样:
public void StartTimer()
{
//A note on the dispatcherTimer http://www.wpf-tutorial.com/misc/dispatchertimer/
var timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 10); // Each every n milliseconds (set low to avoid flicker)
timer.Tick += EachTick;
timer.Start();
}
// A testing counter
int counter = 0;
// Raised every tick while the DispatcherTimer is active.
private void EachTick(object sender, object e)
{ etc
答案 0 :(得分:0)
内置计时器并不十分准确。使用此代码段。我多次使用这个计时器。这个计时器非常准确。感谢John
public class AccurateTimer
{
private delegate void TimerEventDel(int id, int msg, IntPtr user, int dw1, int dw2);
private const int TIME_PERIODIC = 1;
private const int EVENT_TYPE = TIME_PERIODIC;
[DllImport("winmm.dll")]
private static extern int timeBeginPeriod(int msec);
[DllImport("winmm.dll")]
private static extern int timeEndPeriod(int msec);
[DllImport("winmm.dll")]
private static extern int timeSetEvent(int delay, int resolution, TimerEventDel handler, IntPtr user, int eventType);
private readonly int _mTimerId;
public AccurateTimer(int delay)
{
timeBeginPeriod(1);
_mTimerId = timeSetEvent(delay, 0, TimerTick, IntPtr.Zero, EVENT_TYPE);
}
public void Stop()
{
timeEndPeriod(1);
System.Threading.Thread.Sleep(100);// Ensure callbacks are drained
}
private void TimerTick(int id, int msg, IntPtr user, int dw1, int dw2)
{
Console.WriteLine("Tick " + DateTime.Now.TimeOfDay.TotalMilliseconds);
}
}