我寫了一個普通的調度程序定時器方法來創建WPF中的gameloop。我注意到,如果它設置爲比200毫秒更短的時間間隔,它不會正確追上。如何爲我的遊戲獲得更好的計時事件?
我在屏幕上打印了秒(見下面的代碼),並將其與我的手錶進行了比較。設置爲500毫秒,沒關係,但如果我將其設置得低得多,則會有很大差異。我嘗試了10毫秒的設置,這意味着屏幕上的時間在(實際)時間內只傳遞了38秒! (請注意,我的所有遊戲引擎代碼在測試期間都被移除了,所以它只是被調用的計時器循環。此外,如果我從VS或Debug文件夾中的exe文件運行代碼,則無關緊要。)
請注意,我創建的遊戲運行流暢,只是我的(標準)Each_Tick方法不會在正確的時間被調用。這反過來意味着我的遊戲在更快的計算機上運行得更快。
那麼如何保持正確的時間跟蹤並確保Each_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
您假定無限定時器精度,它不存在。除了添加TimeSpans並因此累積不準確之外,最好使用'DateTime.Now'來獲取當前的確切時間。這樣你可以使你的遊戲獨立於定時器的不準確性。 – Clemens
謝謝Clemens,那正是我所希望的那種智慧。 :) – user2040543
一個問題:DateTime.Now總是正確到毫秒?如果是這樣的話,我可以儘可能快地運行遊戲(比如每10分鐘向Every_Tick發送一次all),然後將每個遊戲對象的移動距離與自上次調用Each_Tick(或如此)以來所經過的時間相除。然後,一臺快速電腦將獲得更流暢的體驗,但所有電腦都將獲得相同的速度。 – user2040543