6

スレッドを使用してキャンバスに描画して単純なゲームエンジンを作成しようとしていますが、説明できない奇妙な問題がいくつかあります。この「ゲーム」の目的は、キャンバス上に毎秒円を描くことです。これは機能しますが、私が望む方法ではありません。アプリが2つのキャンバスを切り替えて各キャンバスに円を追加しているようです。そのため、同じ数の円で異なる場所にある2つのキャンバスを毎秒切り替えることができます。キャンバス上。

何が間違っているのかわかりませんが、Treaddingについてはあまり詳しくありません。これは、Androidデバイスに搭載されているコアの数などと関係がありますか?

私のコードを以下に示します。そのため、スレッドを開始し、キャンバス上に1秒ごとに円を描くanimationthreadにリンクするlayoutfileを使用するlaunchthreadを使用します。(toucheventは無視できますが、まだ使用されていません)。

プロジェクトはメインのlaunchthreadから存在します:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

このレイアウトファイルを使用します:

<?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.androidtesting.AnimationView
            android:id="@+id/aview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"/>
</FrameLayout>

そして、内部Threadクラスを持つ私のSurfaceviewクラス:

class AnimationView extends SurfaceView implements SurfaceHolder.Callback {
    private boolean touched = false;
    private float touched_x, touched_y = 0;
    private Paint paint;
    private Canvas c;
    private Random random;
    private AnimationThread thread;

    public AnimationView(Context context, AttributeSet attrs) {
        super(context, attrs);

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

        thread = new AnimationThread(holder);
    }

    class AnimationThread extends Thread {
        private boolean mRun;       
        private SurfaceHolder mSurfaceHolder;        

        public AnimationThread(SurfaceHolder surfaceHolder) {
            mSurfaceHolder = surfaceHolder;
            paint = new Paint();
            paint.setARGB(255,255,255,255);
            paint.setTextSize(32);
        }

        @Override
        public void run() {
            while (mRun) {
                c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {                 
                        doDraw(c);
                        sleep(1000);
                    }
                } catch (Exception e) {                 
                    e.printStackTrace();
                }finally {
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

        private void doDraw(Canvas canvas) {
            //clear the canvas
            //canvas.drawColor(Color.BLACK);                        

            random = new Random();
            int w = canvas.getWidth();
            int h = canvas.getHeight();
            int x = random.nextInt(w-50); 
            int y = random.nextInt(h-50);
            int r = random.nextInt(255);
            int g = random.nextInt(255);
            int b = random.nextInt(255);
            int size = 20;
            canvas.drawCircle(x,y,size,paint);            
            canvas.restore();
        }
        public void setRunning(boolean b) {
            mRun = b;
        }
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
           touched_x = event.getX();
           touched_y = event.getY();

           int action = event.getAction();

           switch(action){
                case MotionEvent.ACTION_DOWN:           
                    touched = true;
                    break;
                case MotionEvent.ACTION_MOVE:
                    touched = true;
                    break;        
                default:
                    touched = false;
                    break;
           }

           return true;
    }

    public void surfaceCreated(SurfaceHolder holder) {
        thread.setRunning(true);
        thread.start();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }
}
4

2 に答える 2

4

アプリが2つのキャンバスを切り替えているようです

はい、これがその仕組みです。これはダブルバッファリングと呼ばれ、毎回すべてのフレームを再描画する必要があります。

サーフェスのコンテンツがunlockCanvas()とlockCanvas()の間で保持されることはありません。このため、サーフェス領域内のすべてのピクセルを書き込む必要があります。

したがって、この行をコードでコメント解除する必要がありcanvas.drawColor(Color.BLACK)ます。

Thread.sleep(1000)また、キャンバスがロックされている間は電話をかけないでください。飢餓の問題が発生します。

于 2012-10-15T13:27:22.550 に答える
0

これは機能しているようですが、指摘すべき小さなエラーに気づきました。

事前にcanvas.save()を呼び出さずにcanvas.restore()を呼び出しました。CanvasのAndroid開発者向けリファレンスから:「save()が呼び出された回数よりもrestore()を何度も呼び出すのはエラーです。」

あなたの場合、canvas.save()を呼び出す理由は見当たらないので、canvas.restore()の呼び出しを削除する必要があります。

于 2013-05-03T06:16:38.347 に答える