我怎样才能为我的游戏获得更好的定时事件? [英] How can I get better timed events for my games?

查看:31
本文介绍了我怎样才能为我的游戏获得更好的定时事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个普通的调度器计时器方法,用于在 WPF 中创建游戏循环.但我注意到,如果将其设置为比 200 毫秒更短的时间间隔,则它无法正确赶上.

I have written an ordinary dispatcher timer method for creating a gameloop in WPF. I notice though that if it is set to a shorter interval than say 200 ms, it doesn't catch up correctly.

我打印了屏幕显示的秒数(请参阅下面的代码)并将其与我的手表进行比较.设置为 500 毫秒是可以的,但是如果我将它设置得低得多,则会出现巨大差异.我尝试了 10 毫秒的设置,这意味着屏幕上的时间在一(真实)分钟内只过去了 38 秒!(请注意,我所有的游戏引擎代码在测试过程中都被删除了,所以它只是调用了计时器循环.另外,我是从 VS 运行代码还是从 Debug 文件夹中的 exe 文件运行都没有关系.)

I printed the seconds to screen (see code below) and compared it to my wrist watch. With a setting of 500 ms, it's okay, but if I set it much lower there is a huge discrepancy. I tried a setting of 10 ms, and that meant that the time onscreen passed only 38 seconds in a (real) minute! (Note that all my game engine code was removed during testing, so it's just the timer loop that is called. Also, it doesn't matter if I run the code from VS or the exe file in the Debug folder.)

请注意,我创建的游戏运行流畅,只是我的(标准)Each_Tick 方法没有在正确的时间被调用.这反过来意味着我的游戏将在更快的计算机上运行得更快.

Note that the games I create run smoothly, it's just that my (standard) Each_Tick method doesn't get called at the correct times. This in turn means that my games will run faster on a faster computer.

那么我如何正确跟踪时间并确保 Each_Tick 方法同时触发,而与所使用的计算机(或手机)无关?也就是说,我宁愿对游戏对象的数量、碰撞检测精度等进行限制,但要按时进行,而不是尽可能快地进行.换句话说,如果我将计时器增量值设置为 50 毫秒(我认为这是合理的,因为这意味着每秒 20 次),我真的希望游戏每秒更新 20 次.

So how do I keep correct track of time and make sure that the Each_Tick method fires at the same time, independently of the computer (or cellphone) used? That is, I would rather have a limit on the number of game objects, collision detection precision etc, but on time, rather than just going as fast as possible. Put differently, if I set the timer increment value to 50ms (which I think is reasonable as that would mean 20 times per second), I really want the game to be updated 20 times per second.

如果可以避免的话,我真的不想进入线程等,因为游戏本身现在运行良好.我只是想让它们以相同的速度播放.

I really don't want to get into threading etc if it's possible to avoid it, as the games themselves run fine now. I just want them to play back at the same speed.

我在 如何通过准确地使用调度程序计时器来控制 WPF 中的帧速率? 但这仍然没有回答我的问题:如何让我的游戏以相同的速度运行,而不管(现代)计算机/单元如何手机,是 WPF/UWP 还是其他什么?

I looked up some great replies at How to control frame rate in WPF by using dispatcher timer accurately? but this still doesn't answer my question: how do I get my games to run at the same speed, regardless of (modern) computer/cell phone and whether it's WPF/UWP or perhaps something else?

或者这是不可能以相当简单的方式完成的,我应该接受游戏速度取决于所使用的计算机?

Or is this impossible to do in a rather easy manner, and I should just accept that game speed depends on the computer used?

谢谢!

代码:

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

请注意,上面的代码是为了测试目的而添加的.原始代码(面临同样的问题)如下所示:

Note that the code above was added for testing purposes. The original code (facing the same problems) looks like this:

    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

推荐答案

内置计时器不是很准确.使用此代码片段.我用过这个计时器很多次了.这个计时器非常准确.感谢约翰

Build in timers are not very accurate. Use this code snippet. Ive used this timer many times. This timer is really accurate. Kudos to 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);
        }
    }

这篇关于我怎样才能为我的游戏获得更好的定时事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆