2012-10-15 11 views
6

スレッドを使用してキャンバスに描画して簡単なゲームエンジンを作成しようとしていますが、説明できない奇妙な問題があります。 この「ゲーム」の目的は、キャンバスに1秒ごとに円を描くことです。 これは動作しますが、私が動作させたい方法ではありません。アプリは2つのカンバス間を切り替えて、各キャンバスに円を追加しているので、2つのカンバスを1秒ごとに同じ円数で切り替えますキャンバスに置く。スレッドを使用したAndroid SurfaceViewキャンバス描画

私は何が間違っているのか分かりませんが、私はそれに慣れていません、それは私のアンドロイドデバイスが持っているか何かのコアと何か関係がありますか?

私のコードは以下のとおりです。スレッドを開始し、毎秒キャンバスに円を描画するanimationthreadにリンクするレイアウトファイルを使用するlaunchthreadを使用します。 (toucheventは無視できますが、まだ使用されていません)。

プロジェクトは、メインlaunchthreadの外に存在する:

<?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) { 
      } 
     } 
    } 
} 
+0

あなたのコードでAnimationView2にする必要がありますか?修正されたバージョンは高く評価されます。 – RichieHH

+0

(psはサンプルの例からコードをコピーするときに(これは軽度に変更されたLunarLanderです)、バグハンティングが容易になるので常にそれを述べるのが最良です))。 – RichieHH

答えて

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

public class MainActivity extends Activity { 

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

アプリが2つのcaの間で切り替わっているようですネバーズ

はい、これはどのように動作するのですか。また、ダブルバッファリングと呼ばれ、あなたはすべてのフレームeach timeを再描画する必要がありますされています

表面の内容は(unlockCanvas間で保存されることはありません)とlockCanvas()、このような理由のために、表面領域内のすべてのピクセルがなければなりません書きました。

このコードでは、この行のコメントを外す必要があります。canvas.drawColor(Color.BLACK)

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

+0

あなたの答えをありがとう、私は私のサークルオブジェクトをすべて保持し、円を描画する描画メソッドでArrayListをループArrayListを言ういくつかの種類が必要ですか? – randomizer

+0

1秒ごとにサークルを追加し、一度にすべてを描画したい場合は、すべての情報をリストに格納し、各フレームをトラバースしてすべての円を描画する必要があります。 –

+0

Ok thx、今はすべて走っているよ:) – randomizer

0

あなたはこの作業をしているようですが、私は指摘しなければならない小さなエラーに気付きました。

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

あなたのケースでcanvas.save()を呼び出す理由は何もないので、canvas.restore()の呼び出しを削除する必要があります。

+0

これで私を助けてもらえますか? http://stackoverflow.com/questions/33909257/canvas-draw-functions-not-working-after-screen-locked-and-unlocked – Jas

関連する問題