游戏以60fps的速度运行,但在减速后,它会以超快的速度运行几秒钟

时间:2016-01-02 02:05:04

标签: java timedelta

我正在开发一个基础游戏。大多数时候游戏都尊重" 60fps的上限,但是当我故意将fps设置为10fps 5秒(通过调试)来测试游戏渲染和游戏逻辑工作分离时,会发生的事情是在我将游戏fps设置为60fps之后,对于一些几秒钟游戏忽略了" cap"并以10000fps的速度运行,然后再回到上限。所有这一切的原因在于,我希望我的游戏以可变的fps运行,但在所有机器上都保持不变的逻辑速度,但是我不明白为什么我的游戏大部分时间都尊重上限而且从不高于60fps但是当发生减速或滞后尖峰,游戏以超快的速度运行1-2秒,然后恢复正常。无论用户是否运行坏电脑并且游戏以5fps运行,我想要的是确保游戏永远不会超过我的硬帽。

我是否需要实现"跳过的帧"系统什么的? 仅供参考,我的游戏逻辑很轻,但渲染非常重。

new Thread(){
        public void run(){
            long hintPoint = System.currentTimeMillis();
            long nexttickG = System.currentTimeMillis();
            long nexttickL = System.currentTimeMillis();
            long nexttickV = System.currentTimeMillis();
            long ticktimeV = 1000;
            long LogicCap = 60;
            long ticktimeL = 1000/LogicCap;
            short frames = 60;

            while(isRunning){

                if(Main.servbot){
                    try {
                        Thread.sleep(15);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);

                short FramesCap = GLOBAL_FPS_CAP;
                long ticktimeG = 1000/FramesCap;

                if (System.currentTimeMillis()>nexttickG){
                    Render();
                    long elapsed = System.currentTimeMillis() - hintPoint;
                    frames=(short)((long)1000/(Math.max(elapsed,1)));
                    hintPoint = System.currentTimeMillis();
                    nexttickG+=ticktimeG;
                }

                if (System.currentTimeMillis()>nexttickL){
                    GameLoop();
                    nexttickL+=ticktimeL;
                }

                if (System.currentTimeMillis()>nexttickV){
                    GLOBAL_FPS_HINT = frames;

                    nexttickV+=ticktimeV;
                }

                Thread.yield();

            }

        }
    }.start();
}

2 个答案:

答案 0 :(得分:2)

首先,如果可能,请使用.currentTimeMillis()而不是FPS,因为第二个更容易出错。

其次,考虑实施"ad-hoc dictionary"系统,其中Game-World Timegame-world 独立于其他

Delta-Time是动画游戏 之类的正确循环模式(基本上是程序化的,系统化的,有时候是 > time-drift bugs数据的混乱动画 ,因为它是最简单的模式,避免了大多数幼稚/简单化的 animation-loop { {1}}或game-loop实施。

DELTA-TIME

有关天真循环实现问题的完整解释,以及Delta-Time如何解决时间漂移问题 (因此,使用它的原因) ,看看Here's an example of how to implement a Delta-Time game-loop in Java.this article,它们详细解释了游戏循环中的差异。

答案 1 :(得分:1)

这些变化有帮助吗? (见下面的代码,查找/ * new * /)。

推理:您是否在run()方法中设置了断点? 你修改了哪些var

在修改var以更改帧速率时,System.currentTimeMillis()中有多少毫秒的时间?好像如果需要3或4(可能是12)秒来进行更改并恢复执行,你的nextTickL和nextTickG值将远远落后于System.currentTimeMillis()并且可能需要大量的+ = ticktimeG来追赶到系统时钟。

new Thread(){
    public void run(){
        long hintPoint = System.currentTimeMillis();
        long nexttickG = System.currentTimeMillis();
        long nexttickL = System.currentTimeMillis();
        long nexttickV = System.currentTimeMillis();
        long ticktimeV = 1000;
        long LogicCap = 60;
        long ticktimeL = 1000/LogicCap;
        short frames = 60;

        while(isRunning){

            if(Main.servbot){
                try {
                    Thread.sleep(15);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            GLOBAL_FPS_CAP=(short)Utils.Clamp(GLOBAL_FPS_CAP,1, 333);

            short FramesCap = GLOBAL_FPS_CAP;
            long ticktimeG = 1000/FramesCap;

            if (System.currentTimeMillis()>nexttickG){
                Render();
                long elapsed = System.currentTimeMillis() - hintPoint;
                frames=(short)((long)1000/(Math.max(elapsed,1)));
                hintPoint = System.currentTimeMillis();
                nexttickG+=ticktimeG;
   /*new*/      if( nexttickG < System.currentTimeMillis() ) {
   /*new*/         // major clock skew somehow, reset.
   /*new*/         nexttickG = System.currentTimeMillis() + ticktimeG;
   /*new*/      }
            }

            if (System.currentTimeMillis()>nexttickL){
                GameLoop();
                nexttickL+=ticktimeL;
   /*new*/      if( nexttickL < System.currentTimeMillis() ) {
   /*new*/         // major clock skew somehow, reset.
   /*new*/         nexttickL = System.currentTimeMillis() + ticktimeL;
   /*new*/      }
            }

            if (System.currentTimeMillis()>nexttickV){
                GLOBAL_FPS_HINT = frames;

                nexttickV+=ticktimeV;
            }

            Thread.yield();

        }

    }
}.start();