【问题标题】:Unstable speed of gameloop游戏循环速度不稳定
【发布时间】:2011-10-13 18:26:45
【问题描述】:

我正在 Android 上使用 OpenGL(-es) 制作一个简单的突围游戏。最初,我在同一个循环中更新了游戏状态和绘图调用:onDrawFrame。现在我决定将两者分开,只将渲染调用留在 onDrawFrame 中,而游戏状态则在另一个 Thread 中进行管理:

public void run() {
    Log.d("GameLogicThread", "GameLogicThread started");
    final long UPDATE_INTERVAL = 1000000000 / 30;
    long endingTime;
    int timeElapsed;
    long startingTime = System.nanoTime();

    while (!running) {// wait for it...

    }
    while (running) {
        endingTime = System.nanoTime();
        timeElapsed = (int) (endingTime - startingTime);
        Log.d("timeElapsed",Integer.toString(timeElapsed));
        if (timeElapsed < UPDATE_INTERVAL-timeElapsed){
            try {
                Thread.sleep(timeElapsed);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        startingTime = System.nanoTime();
        Game.updateGame(timeElapsed);
    }

编辑
我现在已经像这样更改了代码^^,但它仍然无法正常工作..

是循环本身出了什么问题,还是我应该看看外面(可能不是,因为在移动代码之前它工作得很好)。我该怎么办?

【问题讨论】:

  • “因为在移动代码之前它工作得很好”
  • 首先我有代码来更新游戏的状态(如对象位置),就像上面的那个,在我的绘图循环中调用 onDrawFrame(查找它,它被 openGL 自动调用),现在我把它放在一个单独的线程中,从那里你可以看到上面的 run() 方法......
  • @pst 我认为“工作得很好”他的意思是 timeElapsed 总是 > 0 这不是更好。现在他让它跑得更快了。

标签: java android opengl-es timing


【解决方案1】:

在下面的 cmets 中指出/讨论了一些逻辑错误:

    endingTime = System.currentTimeMillis();
    timeElapsed = (int) (endingTime - startingTime);
    // Why is the "elapsed" time being waited? Hmm.
    // If *any* wait is being done (I'd recommend sleep(0) for starters)
    // it should be the MAXIMUM desired cycle time MINUS the
    // currently used cycle time (MINUS some fudge factor).
    if (timeElapsed < UPDATE_INTERVAL) // I dislike hanging blocks...
        try {
            Thread.sleep(timeElapsed);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    startingTime = System.currentTimeMillis();
    // The game needs to know the TOTAL time elapsed since
    // the last update, not the time "until before the yield".
    // This will likely be passed fictitiously small values as
    // it is only time the the LAST updateGame took to run.
    Game.updateGame(timeElapsed);

我永远不会期望看到 timeElapsed(传递给 updateGame)低于 10 毫秒,sleep(...) 和更正的时间计算。

但是,它可能没有所需的精度(将最小循环长度增加到 1/30 秒,这将由固定的数学计算得出,这会使这一点不那么重要):请参阅 Cristian Vrabie 的回答有关更高分辨率计时器的建议。 (可能有一些更好的 3rd-party 替代品专为此而设计——在“普通”Java 中——我不编写 Android ;-)

编码愉快。

【讨论】:

  • 正确!我错过了他在屈服之前通过时间的事实。说到yield,它可能比sleep(0) 更好,而且也不例外:goo.gl/B4AzF 不确定Java 是否已经在0 睡眠的掩护下做到了这一点。
  • 我现在(稍微)修改了上面的代码,但仍然没有解决。另外,你有这样的第 3 方替代品的一些很好的例子吗?
  • @user717572 更新代码仍然不正确。请参考上面的所有 cmets。每条评论是什么意思/暗示?如何解决(多个) 问题? 到底是什么 timeElapsed &lt; UPDATE_INTERVAL-timeElapsed 应该做什么?
【解决方案2】:

在我看来,循环并没有损坏。 分离线程绝对是一个好方法,否则当帧的渲染时间过长时,您会遇到严重的问题。

您是否尝试过使用nanoTime() 来提高准确性?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    相关资源
    最近更新 更多