http://blog.csdn.net/hitachi_ht/article/details/38150955
The practice of many predecessors proves that the accuracy of Timers in C# can not meet the requirement of 60fps. This can be done as an experiment, using two Timers, one 1s, the other 0.01667s, and then counting + 1 for tick s of the latter timer, counting the number of + 1 for each second in front and counting the number of + 1 for the latter, you will find that there may be only about 30 times per second.
About the better timing system google also has, that is, the use of this performance counter, the measurement of longitude can be very high.
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("kernel32")]
- private static extern bool QueryPerformanceFrequency (ref long PerformanceFrequency);
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("kernel32")]
- private static extern bool QueryPerformanceCounter (ref long PerformanceCounter);
To incorporate this into Gameloop, I wrote a class for timing.
In this way, we can get a relatively accurate stopwatch.
- public class PreciseTimer {
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("kernel32")]
- private static extern bool QueryPerformanceFrequency (ref long PerformanceFrequency);
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("kernel32")]
- private static extern bool QueryPerformanceCounter (ref long PerformanceCounter);
- long _tickPerSecond = 0;
- long _previousElapsedTime = 0;
- public PreciseTimer () {
- QueryPerformanceFrequency(ref _tickPerSecond);
- GetElapsedTime();
- }
- public double GetElapsedTime () {
- long Time = 0;
- QueryPerformanceCounter(ref Time);
- double ElapsedTime = (double)(Time - _previousElapsedTime) / (double)_tickPerSecond;
- _previousElapsedTime = Time;
- return ElapsedTime;
- }
- }
Then, we need the Message processing mechanism of windows, where we use the Message in C.
And we need the PeekMessage function in C.
- [StructLayout(LayoutKind.Sequential)]
- public struct Message {
- public IntPtr hWnd;
- public Int32 Msg;
- public IntPtr wParam;
- public IntPtr lParam;
- public uint time;
- public System.Drawing.Point P;
- }
Then with these things, we came up with a class called TimeController.
- [System.Security.SuppressUnmanagedCodeSecurity]
- [DllImport("User32.dll", CharSet = CharSet.Auto)]
- public static extern bool PeekMessage (
- out Message Msg,
- IntPtr hWnd,
- uint messageFilterMin,
- uint messageFilterMax,
- uint flags);
Then we just need to add a Gameloop function to Form1.cs
- PreciseTimer _preciseTimer = new PreciseTimer();
- public delegate void LoopCallBack (double ElapsedTime);
- LoopCallBack _loopCallBack;
- public TimeController (LoopCallBack CallBack) {
- _loopCallBack = CallBack;
- Application.Idle += new EventHandler(OnApplicationEnterIdle);
- }
- private void OnApplicationEnterIdle (object sender, EventArgs e) {
- while (IsAppStillIdle())
- _loopCallBack(_preciseTimer.GetElapsedTime());
- }
- private bool IsAppStillIdle () {
- Message Msg;
- return !PeekMessage(out Msg, IntPtr.Zero, 0, 0, 0);
- }
Finally, time Controller is defined.
- void GameLoop (double ElapsedTime) {
- }
And put Gameloop in it.
- TimeController timeController;
- timeController = new TimeController(GameLoop);
That's it.
These things are hard to find on the Internet, so write them down.