2012-03-28 6 views
7

私はopenglを使ってアンドロイドで簡単なゲームを書こうと思っていましたが、すぐにメインゲームのループに悩まされました。私がここで読んでいる通り:http://developer.android.com/resources/tutorials/opengl/opengl-es10.htmlアプリは表面を再描画する必要があるたびにpublic void onDrawFrame(GL10 gl)を呼び出します。それともそういうものか。私の問題は、描画呼び出しに依存しない更新ループを作成する方法でした。つまり、そのようには動作しません。デバイス(アプリケーション?)がサーフェスを再描画したいとき(または間違っていますか?)に限り、ゲームロジックを更新できません。android openglで適切に更新/描画ループを作成するには?

私はいくつかのグーグルで私は結論に私は更新ループのための別のスレッドを作成する必要が来た。しかし、私は別の問題を抱えていました。一つのスレッドが描画を担当し、もう一つがゲームロジックを更新する世話をしていました。私はそれらを協力させる方法を知らなかったのです。まず、2つのクラス(少なくとも私の実装では)だったので、同じゲーム変数とオブジェクト(スプライト、タイマー、さまざまな変数、カウンターなど)を使うことができませんでした。彼らの仕事)。今私は何とかそれらを両方とも一つのクラスに詰めることができると思う。しかし、2番目に、私は何とか2つのスレッドを同期させる必要がありました。 run()update()方法で

  • public class UpdateThread implements Runnableを描くの世話をしonSurfaceCreated()方法で
    1. public class MyRenderer implements GLSurfaceView.Renderer

      • 3クラス:

        は最後に、私はこの一般的な考えで出てきました。 run()は、1秒間に正確に60回、update()メソッドを呼び出していました(私は固定ステップループが必要でした)

      • public class SpritesHolderすべてのゲームオブジェクト/変数/もの(スプライト、タイマー、状態変数など)すべてのフィールドが公開されています。
  • だから、基本的 SpritesHolderクラスが一つの場所に、必要なすべての変数を保持する箱だったので、 MyRendererUpdateThreadクラスがそれにアクセスし、それを使用することができます。同期用として
  • - 私はちょうどこのようになめらかでした:両方のスレッドが同時にspritesHolderを使用しないように

    public void onDrawFrame(GL10 gl) 
    { 
        synchronized (spritesHolder) 
        { 
         // whole method code... 
        } 
    } 
    

    public void update(float delta) 
    { 
        synchronized (spritesHolder) 
        { 
         // whole method code... 
        } 
    } 
    

    と。更新は毎秒60回行われ、app(device?)が必要なときはいつでも描画が行われました。

  • 話がたくさんあり、申し訳ありませんが、私はこの投稿をほとんど書き終えました。 ;)とにかく - とにかく - これは(上記の)作品と私はこの「テンプレート」に基づいていくつかのゲームを書いていましたが、私のアイデアは狂っているかもしれないと思います。私はすべてのコメントとアドバイスにとても感謝しています。

    +0

    ただ1語:http://obviam.net/ :) – akonsu

    答えて

    1

    あなたのソリューションはおそらく動作しますが、パフォーマンスが最適ではない可能性があります。それについて考えると、レンダリングスレッドと更新スレッドは、実際には100%排他的である必要はありません。

    私は最近、私のゲームのためにこれを考えてしばらく過ごし、これは私が来てしまったものです(必ずしも良くはなく、考えるだけで何か):

    すべてのレンダリング可能なオブジェクトの場合は、私が持っています更新スレッドが所有するオブジェクト、およびオブジェクトを描画する方法(モデル行列、uniform値、meshIDなど)を含むプレーンコンテナであるレンダリングスレッドが所有する別のオブジェクトです。レンダリング可能なオブジェクトの最終的な位置と値をすべて計算した更新スレッドを実行してから、そのフレームで変更された値をレンダリング可能なスレッドのオブジェクトに渡す小さなウィンドウを同期します。新しい情報が通過するとすぐに、フレームレンダリングが開始され、次の更新フレームが同時に実行されます。小さな除外ウィンドウしかないので、ほとんどの場合、更新とスレッドの描画を同時に実行できます。

    1

    OpenGLでこれを使用していませんでしたが、UpdateThreadはTimerTaskにする必要があります。あなたのTimerTaskを内

    new Timer().schedule(new UpdateThread(view), 0, 15); //where view is your view, and 15 is the wait time 
    

    とあなたの活動の立ち上げ、それをで はハンドラでビューを呼び出します。あなたのUpdateThreadのrunメソッドで例えば(ビュークラスで)

    Handler refreshHandler = new Handler() { 
        public void handleMessage(Message msg) { 
           //Handle it; e.g. for canvas invalidate() 
          }}; 
    

    次の操作を行います。

    view.refreshHandler.sendMessage(new Message()); 
    

    は、今ではあなたのgameloopとは無関係です。さらに、あなたのgameloopはMainActivityではなくThread(単方向オブジェクト指向)であるべきです。

    関連する問題