私は最近ゲーム開発を趣味として追求しており、ゲーム開発のインとアウトを学ぶためには、ゲームを作成し、すべてを自分でレンダリングする必要があると判断しました(ゲームエンジンを使用せずに)。これはかなり複雑であることがわかりましたが、私は大きな進歩を遂げています。ただし、Androidフォンがグラフィックをレンダリングする方法に関連している可能性があると思われる問題が発生しました。この問題についての説明が必要です。
問題
私のゲームには、大砲に一連のボールが含まれています。ユーザーが画面を押すと、大砲がボールを発射し、エンジン(実装中)が位置情報の更新とそこからの衝突検出を処理します。さて、衝突検出を実装する前は、ゲームは非常にスムーズに応答しましたが、境界内にある場合にのみビードを描画し、それ以外の場合は壁から「跳ね返る」ようにエンジンに指示すると、エンジンはループの実行時間が大幅に長くなりました。
これは、ユーザーエクスペリエンスに提供しているレイテンシがなければ、問題ありません。たとえば、今画面に触れたとき、ボールが画面内を移動しているように表示されるまで約2秒かかり、まったく表示されない場合もあります。以前は、反応は瞬間的でした。
さらに、物理エンジンの衝突検出部分をコメントアウトすると、通常の応答動作が再開されます。
私がこの行動を引き起こしていると思うこと
注:私はこの仮定を取り消しました(以下の「デバッグ情報」を参照してください)。
私のゲームにはフレームリミッターが実装されておらず、ハードウェアで可能な限り高速にレンダリングされているため、画面に非常に多くの古いフレーム(バッファー内など)を描画していると思います物理を更新している間、描画に忙しい。これまでの私のデバッグでは、これが当てはまることを示していませんが、他の結論に達することはできません。
いくつかのコード
このコードは、すべてが何をするのかを知らないことを理解するのがかなり混乱することに注意してください。誰かがいくつかのコードを操作することにこだわった場合に備えて、単にそれを含めました。変数は抜粋の下で明確にされています。
PhysicsEngine.updateBeadPositions(float):
private void updateBeadPositions(float delta){
//Update all of the beads currently on the board.
beads = control.getBoard().getValues();
temp_x = 0.0f;
temp_y = 0.0f;
//For each row...
for(Bead[] row : beads){
//For each bead...
for(Bead bead : row){
//If this bead exists...
if(bead != null){
temp_y = (float) (bead.getYCoordinate() * bead.getYVelocity() * delta);
//If the coordinates are within the bounds of the game
if(outwithVerticalBounds(temp_y, control.getBoard())){
//Set the X coordinate equal to the distance * the time differential (delta).
bead.setXCoordinate(temp_x);
//Set the X coordinate equal to the distance * the time differential (delta).
bead.setYCoordinate(temp_y);
}
}
}
}
//If the cannon Bead has been set...
if(control.getCannon().getReleased() != null){
//Update the cannon bead
if(control.getCannon().getReleased().getXVelocity() == PhysicsEngine.VELOCITY_STATIC && control.getCannon().getReleased().getYVelocity() == PhysicsEngine.VELOCITY_STATIC){
control.getCannon().getReleased().setXCoordinate(control.getCannon().getX());
control.getCannon().getReleased().setYCoordinate(control.getCannon().getY() - Cannon.PIVOT_Y_OFFSET);
}
else{
temp_x = control.getCannon().getReleased().getXCoordinate() + (control.getCannon().getReleased().getXVelocity() * delta);
temp_y = control.getCannon().getReleased().getYCoordinate() + (control.getCannon().getReleased().getYVelocity() * delta);
//TODO: Commented out collision checkers!
//If the horizontal coordinates are within the bounds of the game
if(!outwithHorizontalBounds(temp_x, control.getBoard())){
//If the vertical coordinates are within the bounds of game
if(!outwithVerticalBounds(temp_y, control.getBoard())){
//Set the X coordinate equal to the distance * the time differential (delta).
control.getCannon().getReleased().setXCoordinate(temp_x);
//Set the X coordinate equal to the distance * the time differential (delta).
control.getCannon().getReleased().setYCoordinate(temp_y);
}
//Otherwise...
else{
//Bounds off the wall in the y direction
control.getCannon().getReleased().setYVelocity(-1.0f * control.getCannon().getReleased().getYVelocity());
}
}
//Otherwise...
else{
//Bounce off the wall in the x direction (flip the x velocity)
control.getCannon().getReleased().setXVelocity(-1.0f * control.getCannon().getReleased().getXVelocity());
}
}
}
}
ここでは、変数は次のように定義されています。
control
私のゲームコントローラへの参照です。ゲームコードの大部分をパッケージ化しています。beads
現在ボード上のビーズを含む2D配列への参照です(動いているものを除く)。delta
物理エンジンへの以前の呼び出しと現在の呼び出しの間の時間差です
他の説明については、コード内のコメントを参照してください。
PhysicsEngine.outwithHorizontalBounds(float、Board):
private boolean outwithHorizontalBounds(float x, Board board){
//If the horizontal values are within the bounds...
if(x > (board.getRight() - bead_radius)){
return true;
}
if(x < (board.getLeft() + bead_radius)){
return true;
}
//Otherwise, it is not.
return false;
}
メソッドoutwithVerticalBounds(float, Board)
は同等の機能ですが、y方向です。
私の質問
衝突検出については、画面のレンダリングが大幅に抑制されますか?私はそれが非常に集中的な操作であることを知っていますが、私のデバッグは、物理の更新が描画と同時に完了することを示しています。
デバッグ情報
最終更新日:2013年1月29日16:27 EST
これは、これまでに入手したデバッグ情報の集約です。時間の経過に応じてこれを更新します。
update()
私のエンジン内のメソッドは、平均して、.018 ms
実行するだけです。通常、0.020 ms
画面をタップしてビードを離すと、遅延は最大にジャンプします。ドローとゲームの更新の時間を比較した後、私は正しかったように見えます:それらは同時に発生しています。したがって、これは問題ではありませんよね?
FPS
ゲームのは大体ある87
それは(ローエンドで)にランダムにスパイク、60 FPS
しかし、このスパイクがされていないビーズの解放に関連します。これFPS
を行うことには欠点はありません。ビードが解放された後に複雑さが増すのはupdate()
呼び出しだけなので、これは理にかなっています。描画は依然として可能な限り速く行われます。さらなるテストの後、これはスクリーンが物理学より遅れているという事実ではないことが明らかになりました。私はこれに触れたときに画面の背景が白くなる単純なブール値フラグでこれをテストしましたが、これはすぐに発生します。したがって、ビードが描画されない原因は他にもあるはずです。すぐに更新します。
補足情報
これが私の状況を理解するのに役立つ補足情報です。
これをGoogle Nexus 7でテストしています。
マップ上に一度に更新されているビーズがかなりあります(約30)が、移動しているのは1つだけです。
通常、ビードが動き始めた後(最初の遅延の後、実際に描画された場合)は、非常にスムーズに動き続けます。
タッチイベントに反応して更新される他のUI要素が画面上にあることに注意してください。たとえば、大砲にロードされたビーズは、画面がタッチされたときに(リリースされたことを示す)新しいビーズになりますが、モバイルビーズは描画されません。