Я подумал, что поступил сообразительно, используя этот код для цикла игрового потока вместо обычного цикла while(running)
:
@Override
public void run() {
Log.d(TAG, "+ run()");
final long [] old = new long [] { System.currentTimeMillis() };
Log.w(TAG,"Start time=" + old[0]);
Thread loop = new Thread() {
public void run() {
if( running ) {
Canvas canvas = null;
try {
canvas = mSurfaceHolder.lockCanvas(null);
long t = System.currentTimeMillis();
Log.w(TAG,"Loop time=" + t + ", delta=" + (t-old[0]));
old[0] = t;
synchronized( mSurfaceHolder ) {
mGame.update();
mGame.onDraw(canvas);
}
}
finally {
// Do this in finally so that if an exception is thrown
// we don't leave the Surface in an inconsistent state
if( canvas != null ) {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
Log.i(TAG, "Posting thread with delay " + interval + " milliseconds");
handler.postDelayed(this, interval);
}
};
};
Log.i(TAG, "Posting thread with no delay");
handler.post(loop);
Log.d(TAG, "- run()");
}
Первый поток отправляется, затем каждый поток отправляет себя обратно в очередь с заданной задержкой.
Что произвело этот журнал (частичный):
03-09 12:51:22.665: D/GameLoop(3116): + run()
03-09 12:51:22.665: W/GameLoop(3116): Start time=1362826282665
03-09 12:51:22.665: I/GameLoop(3116): Posting thread with no delay
03-09 12:51:22.665: D/GameLoop(3116): - run()
03-09 12:51:22.687: W/GameLoop(3116): Loop time=1362826282691, delta=26
03-09 12:51:22.687: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:22.687: D/GameView(3116): + onWindowFocusChanged(hasWindowFocus:true)
03-09 12:51:22.687: D/GameLoop(3116): + resume()
03-09 12:51:22.687: D/GameLoop(3116): - resume()
03-09 12:51:22.687: D/GameView(3116): - onWindowFocusChanged()
03-09 12:51:22.745: W/GameLoop(3116): Loop time=1362826282745, delta=54
03-09 12:51:22.745: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.284: W/GameLoop(3116): Loop time=1362826283284, delta=539
03-09 12:51:23.285: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.366: W/GameLoop(3116): Loop time=1362826283367, delta=83
03-09 12:51:23.366: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.425: W/GameLoop(3116): Loop time=1362826283426, delta=59
03-09 12:51:23.425: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.495: W/GameLoop(3116): Loop time=1362826283504, delta=78
03-09 12:51:23.505: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.555: W/GameLoop(3116): Loop time=1362826283561, delta=57
03-09 12:51:23.555: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.615: W/GameLoop(3116): Loop time=1362826283622, delta=61
03-09 12:51:23.615: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.675: W/GameLoop(3116): Loop time=1362826283675, delta=53
03-09 12:51:23.686: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.749: W/GameLoop(3116): Loop time=1362826283750, delta=75
03-09 12:51:23.749: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.807: W/GameLoop(3116): Loop time=1362826283808, delta=58
03-09 12:51:23.807: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.875: W/GameLoop(3116): Loop time=1362826283884, delta=76
03-09 12:51:23.875: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:23.936: W/GameLoop(3116): Loop time=1362826283938, delta=54
03-09 12:51:23.946: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:24.006: W/GameLoop(3116): Loop time=1362826284006, delta=68
03-09 12:51:24.006: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:24.065: W/GameLoop(3116): Loop time=1362826284065, delta=59
03-09 12:51:24.065: I/GameLoop(3116): Posting thread with delay 50 milliseconds
03-09 12:51:24.126: W/GameLoop(3116): Loop time=1362826284126, delta=61
03-09 12:51:24.126: I/GameLoop(3116): Posting thread with delay 50 milliseconds
Я знаю, что пост-задержка неточна, но здесь каждый раз она опаздывает, чем требуемые 50 милли.
Мой mGame.update()
метод сейчас пуст, а mGame.onDraw()
рисует 2 прямоугольника, одну строку и один текст. Считаю, что он не особо тяжелый, и все равно не может угнаться за 20FPS.
Как они отрисовывают игры с интенсивной графикой, такие как асфальт, и поддерживают высокий FPS?
Предостережение: это работает в эмуляторе под управлением механизма Intel HAXM, который работает настолько быстро, насколько это возможно в эмуляторе.
Чтобы прояснить, о чем я спрашиваю, это:
Что мне нужно сделать, чтобы достичь высокого FPS в игровом цикле (не требующем больших вычислительных ресурсов)?
Примечание: я знаю, что задержка будет не менее 50 милли. Но меня всегда беспокоят две вещи: второй вызов занимает несколько сотен милли, а точность варьируется от 20 до 10 кадров в секунду, и меня беспокоит, что движение на экране не будет выглядеть равномерным.
Редактировать
Просто для проверки я уменьшил интервал до 20 милли (50 кадров в секунду), а дельта осталась в диапазоне 50-70 милли (эмулятор).
Я увеличил интервал до 83 милли ( 12FPS), а дельта - 87-93 (эмулятор).
Я установил приложение в ASUS TF201 под управлением Nvidia quadcore, и дельта не сильно изменилась.
Вывод таков, что для игр, использующих Canvas и циклы обновления-отрисовки, я не могу подняться выше 20FPS. Разочарование.