Direct2D随笔2——在C#的WinForm环境下创建Gameloop

来源:互联网 发布:剃头理发器软件 编辑:程序博客网 时间:2024/05/22 06:12

经过大量前辈的实践证明,C#中Timer们的精度都无法达到60fps的需求。这一点可以做个实验,用2个Timer,一个1s,另一个0.01667s,然后后面timer的tick时给count+1,前面的每秒统计一下后面有几个+1,就会发现可能每秒只有大概30次左右。

关于比较好的计时系统google上面也有,就是利用这个性能计数器,计量的经度就能到很高了。

[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);

为了把这个融入到Gameloop里面,我写了个类用来计时

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;      }}
这样就可以得到一个相对准确的秒表( ╯□╰ )了。
然后,我们需要windows的消息处理机制,这里我们使用了C里面的Message。

[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;}
并且我们需要C里面的PeekMessage函数。
[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);
然后利用这些东西,我们就拼凑出了一个类,起名叫做TimeController。

      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);      }
然后我们只需要在Form1.cs里面添加一个Gameloop函数

void GameLoop (double ElapsedTime) {}
最后定义出来timeController。
TimeController timeController;
并且将Gameloop放进去

timeController = new TimeController(GameLoop);

就完成了。

这些东西在网上比较难找,所以特意记下来。

0 0
原创粉丝点击