Я думаю, что может быть, что-то не так с некоторым из приведенного выше кода, а скорее неэффективность. Я говорю об этом коде ...
// The important part!
// This starts another thread (let's call this THREAD_B). THREAD_B will run completely
// independent from THREAD_A (above); therefore, FPS changes will not affect how
// our velocity increases our position.
public void startMyLogicThread() {
new Thread() {
public void run() {
// Store the current time values.
long time1 = System.currentTimeMillis();
long time2;
// Once active is false, this loop (and thread) terminates.
while (active) {
try {
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
time2 = System.currentTimeMillis(); // Get current time
int delta = (int) (time2 - time1); // Calculate how long it's been since last update
update(delta); // Call update with our delta
time1 = time2; // Update our time variables.
}
}
}.start(); // Start THREAD_B
}
В частности, я думаю о следующих строках ...
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
Мне кажется, что просто зависание потока, ничего не делая, - пустая трата драгоценного времени на обработку, тогда как на самом деле то, что вы хотите делать, - это выполнение обновлений, тогда, если обновления заняли меньше времени, чем миллис, затем спите поток для разницы того, что было использовано во время обновления и 25 миллис (или любой другой выбранной вами частотой кадров). Таким образом, обновление будет происходить во время рендеринга текущего кадра, и будет завершено, поэтому при следующем обновлении кадра будут использоваться обновленные значения.
Единственная проблема, о которой я могу подумать, заключается в том, что должна произойти какая-то синхронизация, чтобы текущий рендеринг кадра не использовал частично обновленные значения. Возможно, обновите новый экземпляр вашего набора значений, а затем сделайте новый экземпляр текущим экземпляром непосредственно перед рендерингом.
Мне кажется, что я помню, что читал что-то в графической книге о том, что цель состоит в том, чтобы выполнять как можно больше обновлений, оставаясь в пределах желаемой частоты кадров, а затем, и только они, выполнять обновление экрана.
Это, конечно, потребует одного потока для запуска обновлений - если вы используете SurfaceView, рендеринг контролируется этим потоком, когда вы блокируете холст (теоретически, по моему мнению, так или иначе).
Итак, в коде это было бы больше похоже на ...
// Calculate next render time
nextRender = System.currentTimeInMillis() + 25;
while (System.currentTimeInMillis() < nextRender)
{
// All objects must be updated here
update();
// I could see maintaining a pointer to the next object to be updated,
// such that you update as many objects as you can before the next render, and
// then continue the update from where you left off in the next render...
}
// Perform a render (if using a surface view)
c = lockCanvas() blah, blah...
// Paint and unlock
// If using a standard view
postInvalidate();
Удачи, и любой отзыв от любого, кто использует это, несомненно, поможет нам всем чему-то научиться ...
rpbarbati