微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在简单的java游戏循环中提高帧率?

如何解决如何在简单的java游戏循环中提高帧率?

我正在开发一个 Java 2d 游戏,使用这个简单的游戏循环将 FPS 和 UpdatesPS 限制为 60:

public void run() {

        final int MAX_FPS = 60;
        final int MAX_UPS = 60;

        final double fOPTIMAL_TIME = 1000000000 / MAX_FPS;
        final double uOPTIMAL_TIME = 1000000000 / MAX_UPS;

        double uDeltaTime = 0,fDeltaTime = 0;
        int frames = 0,updates = 0;
        long startTime = System.nanoTime();
        long timer = System.currentTimeMillis();

        // GameLOOP starts here
        while (running) {

            long currentTime = System.nanoTime();
            uDeltaTime += (currentTime - startTime);
            fDeltaTime += (currentTime - startTime);
            startTime = currentTime;

            if (uDeltaTime >= uOPTIMAL_TIME) {
                gameUpdate();
                updates++;
                uDeltaTime -= uOPTIMAL_TIME;
            }

            if (fDeltaTime >= fOPTIMAL_TIME) {
                gameRender();
                gameDraw();
                frames++;
                fDeltaTime -= fOPTIMAL_TIME;
            }

            if (System.currentTimeMillis() - timer >= 1000) {

                fps = frames;   //saves the current FPS
                ups = updates;  //saves the current UPS

                updates = 0;
                frames = 0;
                timer += 1000;
            }

        }
    }

循环有效,但在开始游戏后的前大约 10 秒内我只能获得 30 FPS。

等待后,FPS 上升到想要的 60。我没有问题等待几秒钟让程序稳定并达到想要的帧率。但是我找不到像方法一样的原因,因为它在启动后正在获取一个文件而丢弃FPS。

你知道为什么我的引擎需要这么长时间来稳定帧率吗?

感谢您的帮助!

解决方法

我认为这应该可以解决问题:

    public static void run()
    {
        final int desiredFPS = 60;
        final int desiredUPS = 60;
        
        final long updateThreshold = 1000000000 / desiredUPS;
        final long drawThreshold = 1000000000 / desiredFPS;
        
        long lastFPS = 0,lastUPS = 0,lastFPSUPSOutput = 0;
        
        int fps = 0,ups = 0;
        
        loop:
        while(true)
        {
            if((System.nanoTime() - lastFPSUPSOutput) > 1000000000)
            {
                System.out.println("FPS: " + (double)fps);
                System.out.println("UPS: " + (double)ups);
                
                fps = 0;
                ups = 0;
                
                lastFPSUPSOutput = System.nanoTime();
            }
            
            if((System.nanoTime() - lastUPS) > updateThreshold)
            {
                lastUPS = System.nanoTime();
                updateGame();
                ups++;
            }
            
            if((System.nanoTime() - lastFPS) > drawThreshold)
            {
                lastFPS = System.nanoTime();
                drawGame();
                fps++;
            }
            
            // Calculate next frame,or skip if we are running behind
            if(!((System.nanoTime() - lastUPS) > updateThreshold || (System.nanoTime() - lastFPS) > drawThreshold))
            {
                long nextScheduledUP = lastUPS + updateThreshold;
                long nextScheduledDraw = lastFPS + drawThreshold;
                
                long minScheduled = Math.min(nextScheduledUP,nextScheduledDraw);
                
                long nanosToWait = minScheduled - System.nanoTime();
                
                // Just in case
                if(nanosToWait <= 0)
                    continue loop;
                    
                try
                {
                    Thread.sleep(nanosToWait / 1000000);
                } 
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

编辑:我现在解决了这个问题!问题是我在场景更新/绘制后保存了 lastFPS/lastUPS,当我在场景绘制/更新之前设置 lastUPS/lastFPS 时,我们得到了所需的 fps!
这段代码的另一个优点是它不消耗整个cpu核心(我测量了差异,你的代码消耗了100%,而我的代码只消耗了大约10%。如果你想自己测量,请注意,出于某种原因,执行代码的核心会定期切换(至少我测量代码时是这种情况))

顺便说一句,如果您使用 LWJGL(或有直接访问像 GLFW 这样的窗口库)您可以激活 V-Sync,这会将您的 fps 降低到 60 fps。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。