0

LunarLander と同様のフレームワークで、SurfaceView を使用してビットマップを描画する Android ゲーム エンジンを開発しています。私のメイン ゲーム エンジン アクティビティは、以下に示すように、SurfaceView 拡張クラスを表示するようにレイアウトを設定します。

super.onCreate(savedInstanceState);

    setContentView(R.layout.ss_layout);

    SSSurfaceView ssSurfaceView = (SSSurfaceView)findViewById(R.id.surface_view);
    SSSurfaceView.SSViewThread renderThread =
        (SSSurfaceView.SSViewThread) ssSurfaceView.getThread();    

findViewById メソッドは、SurfaceView 拡張クラスのインスタンスを正常に返し、クラス コンストラクターであるこのメソッドで作成されたクラス内で定義したスレッドを実行できます。

public SSSurfaceView(Context context, AttributeSet attributes)
{
    super(context, attributes);

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);

    thread = new SSViewThread(holder, context);
}

コンストラクターは、関連付けられた SurfaceHolder への参照を取得する必要があり、それをスレッド コンストラクターに渡します。holder.lockCanvas(null) が null を返すスレッド実行メソッド内で問題が発生し始めました。これはサーフェスが作成されていないことを意味する可能性があることをどこかで読んだので、surfaceCreated コールバックで true に設定したブール値を使用して if ステートメントを追加しました。

    public void run()
    {
        Canvas canvas = null;
        try
        {
            canvas = holder.lockCanvas(null);
            //I added the condition below
            if(surfaceCreated)
            {
                drawAll(canvas);
            }
        }
        catch(Exception e)
        {
            Log.wtf("SurfaceView", "exception");
        }
        finally
        {
            if(canvas != null)
            {
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }

そして、ここにコールバックがあります:

public void surfaceCreated(SurfaceHolder holder)
{
    surfaceCreated = true;
}

結局のところ、surfaceCreated が呼び出されることはありません。drawAll メソッドが繰り返されないため、私のアプリケーションは灰色の画面を表示し、他には何もしません。起動する layout.xml ファイルは次のとおりです。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <com.bostonwalker.sseng.SSSurfaceView
        android:id="@+id/surface_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>

編集:これは私のコード全体ではありません。例を関連するセクションに限定しようとしました。スレッドはメイン ループで呼び出されますが、時間が経ってもコールバックは起動しません。

編集: UI スレッドで繰り返されるループは次のとおりです。

while(!halt)
    {
        //EDIT: Changed from .run() to .start()
        renderThread.start();
        gameThread.start();
        //Wait for both threads to proceed before continuing
        try
        {
            renderThread.join();
            gameThread.join();
        }
        catch (InterruptedException e)
        {
            //Do nothing
        }

        Thread.currentThread();
        try
        {
            Thread.sleep(2);
        }
        catch (Exception e)
        {
            //Do nothing
        }
    }
4

1 に答える 1

1

描画スレッドはループしません。一度だけ実行して終了します。そして、その最初の実行ではサーフェスがまだ作成されていない可能性があります。

現在持っているコードを、(疑似コードで) のようなある種のループに入れる必要があります。

while(!done) {
   lockTheCanvas();
   drawAFrame();
   unlockTheCanvas();
   sleep(FRAME_INTERVAL);
}

次に、「done」を true に設定して、適切な時点でスレッドを終了する必要があります。sleep() が必要であることに注意してください。そうしないと、スレッドが CPU を独占し、決して終了しません。

于 2013-05-21T02:13:36.580 に答える