2011-12-15 4 views
14

私はしばらくの間、勉強してゲームを作っていましたが、最近私はAndroid向けゲームを開発しようとしています。OpenGLを搭載したAndroid用のペースの速いゲームのゲームロジックをレンダリングから分離する最も良い方法は?

私にとっては、ネイティブC++コードからAndroid Javaへのジャンプはそれほど難しくありませんでしたが、ロジックをレンダリングからどのように分離して維持することができないか考えていました。

私はここや他のサイトで周りに読んでいる:確かに Androidの意志が処理のために問題がないという理由だけで、それのために別のスレッドを作成しない方が良いです

。コード意味

はこのようなものになるだろう:

public void onDrawFrame(GL10 gl) { 
    doLogicCalculations(); 
    clearScreen(); 
    drawSprites(); 
} 

しかし、私はそれが最善のアプローチであるかどうか分かりません。論理をGLRenderer::onDrawFrameメソッドの中に入れれば、どうやって見えるのか気に入らないと思うので、限り、私が知っている限り、このメソッドは、描画することを意味し、私はそこにロジックを置く場合、フレームを遅くする可能性があります。それは私の理解の中でPOOの概念を傷つけることは言うまでもありません。

私はこれは私が計画していた方法です、使用してスレッドが道かもしれないと思う:

主な活動:

public void onCreate(Bundle savedInstanceState) { 
    //set fullscreen, etc 

    GLSurfaceView view = new GLSurfaceView(this); 
    //Configure view 

    GameManager game = new GameManager(); 
    game.start(context, view); 

    setContentView(view); 
} 

GameManager:

OpenGLRenderer renderer; 
Boolean running; 
public void start(Context context, GLSurfaceView view) { 
    this.renderer = new OpenGLRenderer(context); 
    view.setRenderer(this.renderer); 

    //create Texturelib, create sound system... 

    running = true; 
    //create a thread to run GameManager::update() 
} 

public void update(){ 
    while(running){ 
     //update game logic here 
     //put, edit and remove sprites from renderer list 
     //set running to false to quit game 
    } 
} 

そして最後に、OpenGLRenderer:

ListOrMap toDraw; 
public void onDrawFrame(GL10 gl) { 
    for(sprite i : toDraw) 
    { 
     i.draw(); 
    } 
} 

これは大まかな考えであり、完全には完了していません。 このパターンはすべて分離された状態になり、やや良く見えますが、パフォーマンスにとって最適ですか?

私が研究している限り、スレッド化されたゲームのほとんどの例では、キャンバスやサーフェスビューを使用していますが、私はOpenGLESを使用しているので、それらは私のケースに合わないでしょう。

だからここに私の質問です:OpenGLESを使用した場合、レンダリングからの私の ゲームロジックを分離するための最良の方法である

?私の アプリケーションをスレッディングしますか?ロジックを別のメソッドに入れ、drawメソッドを から呼び出すだけですか?

答えて

10

ここには2つの方法があると思います。これは、GLUTを使用するのと同様である、とAndroidは、できるだけ頻繁にこの関数を呼び出します:

  1. onDrawFrame()からすべての更新を行います。 (setRenderMode(RENDERMODE_WHEN_DIRTY)でオフにする)この関数は独自のスレッド(UIスレッドではなく)で呼び出され、ここでロジック更新を呼び出すことを意味します。あなたの最初の問題は、これはちょっと混乱しているようでした。私は同意しましたが、関数の名前がonDrawFrame()であるためです。もしそれがonUpdateScene()と呼ばれていたら、ロジックをアップデートすることはこのモデルをうまく適合させるでしょう。しかし、それは世界で悪いことではなく、このように設計されており、人々はそれをやります。

  2. 与えるロジックは独自のスレッド:入力用のUIスレッドは、ものを描画するためのスレッドonDrawFrame()をレンダリングし、継続的に両方で作業するための論理スレッド:これは、今、あなたは3つのスレッドを扱っているので、より複雑です入力データとレンダリングデータ。フレームレートが低下しても(例えば、正確なコリジョンの応答)、実際に起こっていることの正確なモデルを必要とする場合は、これを使用します。これは、概念的には少しクリーナーですが、実際にはクリーナーではありません。

私は#1をお勧めします。あなたは本当に#2は必要ありません。もしそうなら、後で追加することができますが、ハードウェアが十分に速いので、ほとんどの人が最初のオプションを使用しているだけなので、その周りにデザインする必要はありません。

+0

すばらしい答えスティーブ、ありがとう!私はデザインを台無しにしたくないと思っても、私は#1に従います。私のゲームはアクティブですが、物理学や衝突チェックのような重い計算はありません。ちょうど私の考えについて確かめるために、もし私がそれを選んだら(論理的なスレッドを同期マップに書いて、それを読んでいるスレッドをレンダリングして)質問のスレッドのアプローチが正しいでしょうか? –

+0

ああ、もう1つ。人々は私のロジックアップデートを30fpsに制限すると言っていましたが、これはレンダリングの場合もそうですか?私は、すべての更新のために33msを待つために関数全体を制限するべきですか、または最後の更新以来33msを過ぎた場合にはロジックを更新するだけですか? –

+0

私はあなたがそれを制限する必要はないと思っていますが、おそらくそれはいくつかの携帯電話のそれよりも期待することはありません。これは、最初のHDPI電話機のいくつかのフレームレート(私はDroid 1の周りにあると思います)が限られているため、1秒間に約30回以上のピクセルで画面を描画できなかったためです。おそらく、GPUはそれより速くフレームを送り出すことができますが、CPUは画面をすばやく動かすことができません。これは、私が思うより新しい携帯電話の場合ではありません。 –

6

標準 :)できるだけ簡単にあなたのデザインをしてください(そしておそらく最高の)アプローチは以下の通りです:

public void update(){ 
    while(running){ 
     updateAll(); 
     renderAll(); 
    } 
} 

私はいくつかの瞬間に注意を払う:

  • あなたはupdaterenderメソッドを連続して呼び出す必要があります。を2回呼び出す必要はありません。
  • mあなたのメソッドを設計するようにupdaterenderのみを読み取る
  • OpenGLには独自の「スレッド」がありますので、GL関数を呼び出すと、OpenGLにいくつかのコマンドが送信されます(glFlush() - すべてのコマンドを完了します)
+0

最後のトピックとして、OpenGLrendererのonDrawFrameが別のスレッドで呼び出されていますか?またはGLに関係する他のスレッドへの要求として送信されるgl.GLxxx()だけですか? –

+0

@Gtoknu 'onDrawFrame()'を呼び出すと、あなたは別のスレッドにいます。ここをクリックしてください:http://developer.android.com/reference/android/opengl/GLSurfaceView.Renderer.html –

+0

@SteveBlackwellああ、ありがとう、私はそれを実現していません。しかし、私がonDrawFrame()を呼び出すことができない場合、別のスレッドによって自動的に呼び出されるので、どのようにbrigadirの答えが真になるでしょうか?それらは混乱している。 –

関連する問題