Нестабильная скорость игры - PullRequest
1 голос
/ 13 октября 2011

Я делаю простую игру-прорыв в OpenGL (-ах) на Android. Первоначально у меня было обновление состояния игры и вызовы рисования в одном цикле: onDrawFrame. Теперь я решил разделить их, оставив только вызовы рендеринга в onDrawFrame, а состояние игры было обработано в другом потоке:

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

EDIT
Теперь я изменил код, подобный этому ^^, но он все еще не работает правильно.

Это что-то не так в самом цикле, или я должен смотреть наружу (вероятно, нет, поскольку он прекрасно работал до перемещения кода). Что мне делать?

Ответы [ 2 ]

1 голос
/ 13 октября 2011

Есть несколько логических ошибок, которые указаны / обсуждены в комментариях ниже:

    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 секунды, что будет результатом фиксированной математики, сделает это менее важным): см. Ответ Кристиана Враби для предложения по таймеру с более высоким разрешением. (Могут быть и некоторые лучшие сторонние альтернативы, разработанные специально для этого - в «нормальной» Java - я не программирую Android; -)

Удачного кодирования.

1 голос
/ 13 октября 2011

Цикл для меня не выглядит нарушенным. Переход к отдельным потокам определенно хорош, иначе у вас могут возникнуть серьезные проблемы, когда рендеринг кадра занимает слишком много времени.

Вы пытались использовать nanoTime () для большей точности?

...