私のゲームでは、複数のスレッドがあります。1 つのスレッドが計算スレッドにシグナルを送信し、このスレッドがシグナルを受信した後、ゲームもレンダリングします。
メイン スレッドは次のようになります。これは、私が見た他のゲーム ループから適用したものです。
while(isRunning) {
long now = System.nanoTime();
float elapsed = (now - mStartTime) / 1000000000f;
mStartTime = now;
try {
Log.d("GameThread", "setElapsed = "+elapsed);
mController.setElapsedTime(elapsed);
// send signal to logic barrier to start logic-threads
BaseThread.LogicBarrier.await(); // 1/4
// logic done!
BaseThread.AfterLogicBarrier.await(); // 1/4
// render!
Log.d("GameThread", "RENDERING! -> localTime="+localTime+", Options.TIMESTEP="+Options.TIMESTEP+", interpol = "+(Options.TIMESTEP / localTime));
mController.render((localTime / Options.TIMESTEP));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
// sleep maybe
diff = System.nanoTime() - mStartTime;
mController.fireGameDataChange(GameDataListener.FPS, (int) 1000000000/diff);
if (1000000000 * Options.TIMESTEP - (diff) > 1000000) {
try {
Thread.sleep(0, 999999);
} catch (InterruptedException ex) {
}
}
}
存在する各 ViewObject のレンダリング関数は次のようになります。
mMatrix.reset();
mMatrix.setTranslate(view.getX() - view.getVelocityX() * interpolation), view.getY() + view.getVelocityY)) * interpolation));
mMatrix.preScale((1.0f * view.getWidth() / mBitmap.getWidth()), (1.0f * view.getHeight() / mBitmap.getHeight()));
mMatrix.postRotate(view.getRotation(), view.getX() + view.getWidth()/2f, view.getY() + view.getHeight()/2f);
mCanvas.drawBitmap(mBitmap, mMatrix, mBasicPaint);
これは、ロジック スレッドで起こっていることです。
while(isRunning) {
try {
BaseThread.LogicBarrier.await(); // 3/4
int numSubSteps = 0;
if (Options.SKIP_TICKS != 0) {
// fixed timestep with interpolation
localTime += mController.getElapsedTime();
Log.e("Environment", "localTime="+localTime+" >= "+Options.TIMESTEP+", from elapsed = "+mController.getElapsedTime());
if (localTime >= Options.TIMESTEP) {
//numSubSteps = (int) (localTime/Options.TIMESTEP);
numSubSteps = (int) (localTime/Options.TIMESTEP);
localTime -= numSubSteps * Options.TIMESTEP;
}
}
Log.e("EnvironmentThread", "localTime="+localTime+", numSub="+numSubSteps);
if (numSubSteps != 0) {
// clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
int clampedSubSteps = (numSubSteps > Options.SKIP_TICKS) ? Options.SKIP_TICKS: numSubSteps;
for (int i = 0; i < clampedSubSteps; i++) {
// todo: update game logic -> in time step so no interpolation
mController.refresh(1);
}
}
BaseThread.AfterLogicBarrier.await(); // 3/4
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
スレッドなどを同期するプロセスは問題なく動作します。フレームを 60 に制限すると、1 秒あたり 60 回のリフレッシュが行われ、できるだけ多くのレンダリングが行われます。しかし、昨日から解決しようとしている問題が1つあります-成功していません。
ビューオブジェクトは高速化しています。それらには加速度がなく、速度から単純に得られます。しかし、それらが長く存在すればするほど、それらはより速くなります。なぜこれが起こっているのか誰にも分かりますか?ビットマップ、現在の位置、および速度を取得するために getter メソッドのみを使用しているため、レンダリング関数はビューの位置/速度にまったく干渉してはなりません。
だから私の考えでは、これは補間が原因であると考えていました.
どんな助けでも、どんなアイデアでも、非常に高く評価されます。
以下は、補間を示すロジック スレッドとメイン スレッドの両方からの LogCat 出力と、すべてが実行されるタイミングです。
08-29 17:09:57.603 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.017999122 >= 0.033333335, from elapsed = 0.017043
08-29 17:09:57.603 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.603 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.017999122, numSub=0
08-29 17:09:57.603 26183-26204/com.example.pckg D/GameThread: RENDERING! -> localTime=0.017999122, Options.TIMESTEP=0.033333335, interpol = 1.8519423
08-29 17:09:57.623 26183-26204/com.example.pckg D/GameThread: setElapsed = 0.017807
08-29 17:09:57.623 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.03580612 >= 0.033333335, from elapsed = 0.017807
08-29 17:09:57.623 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.623 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.0024727844, numSub=1
08-29 17:09:57.623 26183-26204/com.example.pckg D/GameThread: RENDERING! -> localTime=0.0024727844, Options.TIMESTEP=0.033333335, interpol = 13.480082
08-29 17:09:57.633 26183-26204/com.example.pckg D/GameThread: setElapsed = 0.013305
08-29 17:09:57.633 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.015777785 >= 0.033333335, from elapsed = 0.013305
08-29 17:09:57.633 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.633 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.015777785, numSub=0
08-29 17:09:57.633 26183-26204/com.example.pckg D/GameThread: RENDERING! -> localTime=0.015777785, Options.TIMESTEP=0.033333335, interpol = 2.1126752
08-29 17:09:57.653 26183-26204/com.example.pckg D/GameThread: setElapsed = 0.018212
08-29 17:09:57.653 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.033989787 >= 0.033333335, from elapsed = 0.018212
08-29 17:09:57.653 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.653 26183-26207/com.example.pckg E/EnvironmentThread: localTime=6.5645203E-4, numSub=1
08-29 17:09:57.653 26183-26204/com.example.pckg D/GameThread: RENDERING! -> localTime=6.5645203E-4, Options.TIMESTEP=0.033333335, interpol = 50.778023
08-29 17:09:57.673 26183-26204/com.example.pckg D/GameThread: setElapsed = 0.01754
08-29 17:09:57.673 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.018196452 >= 0.033333335, from elapsed = 0.01754
08-29 17:09:57.673 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.673 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.018196452, numSub=0
08-29 17:09:57.673 26183-26204/com.example.pckg D/GameThread: RENDERING! -> localTime=0.018196452, Options.TIMESTEP=0.033333335, interpol = 1.831859
08-29 17:09:57.683 26183-26204/com.example.pckg D/GameThread: setElapsed = 0.014516
08-29 17:09:57.683 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.032712452 >= 0.033333335, from elapsed = 0.014516
08-29 17:09:57.683 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.683 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.032712452, numSub=0
08-29 17:09:57.683 26183-26204/com.example.pckg D/GameThread: RENDERING! -> localTime=0.032712452, Options.TIMESTEP=0.033333335, interpol = 1.01898
08-29 17:09:57.703 26183-26204/com.example.pckg D/GameThread: setElapsed = 0.017108
08-29 17:09:57.703 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.049820453 >= 0.033333335, from elapsed = 0.017108
08-29 17:09:57.703 26183-26207/com.example.pckg E/EnvironmentThread: numSubSteps = 0.0
08-29 17:09:57.703 26183-26207/com.example.pckg E/EnvironmentThread: localTime=0.016487118, numSub=1
残念ながら、私の脳は現在遅れており、この時点で何が間違っているのか理解できません.
編集:
私の脳を押してくれてありがとう。さらにデバッグステートメントを追加した後、間違いを見つけました。数学エラーもスレッドの同期ミスもありませんでしたが、ロジック部分 (refresh() メソッド) に単純な "List.clear()" が欠落していたため、リストがクリアされず、同じオブジェクトが移動されました。各計算フレームでより頻繁に-エラーが発生するとは思っていなかったので、ここには投稿しませんでした。
とにかくありがとう。