Androidでゲームエンジンを書こうとしていますが、スレッドにあまり詳しくありません。
私のスレッドには、描画先のサーフェスを保持する属性mSurfaceHolderがあります。私のスレッドのrun()メソッドは次のようになります。
public void run() {
// We're running now
setState(STATE_RUNNING);
// Keep looping while the game is running or paused
while (mState == STATE_RUNNING || mState == STATE_PAUSED) {
synchronized (mSurfaceHolder) {
// If the game is running, update physics etc.
if (mState == STATE_RUNNING) {
updateGame();
}
// Draw the game even if it's paused
drawGame();
}
}
}
STATE_RUNNING
アクティビティがフォアグラウンドにあり、ゲームが実行されている必要があるときの状態を表します。
STATE_PAUSED
別のアクティビティが前面に出たときの状態を表します。一時停止している間も描画する必要がある理由は完全にはわかりませんが、LunarLanderの例から収集したようです。
私が望んでいるのは、アクティビティを見ている間、ゲームが更新されて描画されることです(LogCatを使用してテストします)。そして、ホーム画面に戻るか、別のアクティビティが上に表示されると、描画されます。
アクティビティを見ている間は描画と更新が行われるので、ゲームループ自体は機能します。しかし、私が活動を離れるとき、それは効果がありません。アクティビティのonPause()から呼び出されるスレッドのpause()メソッドは次のとおりです。
public void pause() {
Log.d("Game","Here");
synchronized (mSurfaceHolder) {
Log.d("Game","There");
// If the thread is running, pause it
if (mState == STATE_RUNNING) {
setState(STATE_PAUSED);
}
}
}
ご覧のとおり、このメソッドをテストするために、いくつかのメッセージをログに記録しました。アクティビティを離れたときに見つけたのは、「ここ」はログに記録されていますが、「そこ」はログに記録されていないということです。スレッドに関する知識が限られているので(実際に何が行われるかはほとんどわかりsynchronized
ません)、スレッドがサーフェスホルダーと同期できないため、これが発生すると思います。しかし、なぜ同期しないのかわかりません。アクティビティを終了してから数秒後、LogCatに次の警告が表示されます。
Activity pause timeout for HistoryRecord
なぜこれが起こるのか考えていますか?アクティビティを再開しようとしても問題はありません。スレッドはそのまま実行され続けます。
どうもありがとうございました。
編集:ちょうど何か他のものを発見しました。アクティビティを開始してから約1秒以内にアクティビティを終了すると、スレッドは正常に一時停止します。そして、同じタスクがまだ実行されている間、問題なく再開および一時停止します。なぜ短期間でうまくいくのかわかりませんが、長すぎるとうまくいきません。
編集2:わかりました...私はそれを修正しました。しかし、私は自分がやったことをやるべきではないと思います。mSurfaceHolder
基本的に、pause()メソッドとsetState()メソッド(pause()で使用される)の両方から同期を削除しました。いいえ、想定どおりに機能しますが、同期が必要な理由があると思います。
おそらく私が尋ねる最良の質問はこれです:同期されたブロックを使用してスレッドをオブジェクトと同期する必要があるのはいつですか?この場合、SurfaceHolderと同期する目的は何ですか?