2012-10-15 195 views
6

我正在使用線程繪製畫布以創建簡單的遊戲引擎,但我遇到了一些我無法解釋的奇怪問題。 這個「遊戲」的目的是在畫布上每秒畫一個圓圈。 這是有效的,但不是我希望它工作的方式,似乎應用程序正在兩個畫布之間切換,並在每個畫布上添加一個圓,以便每秒鐘在兩個畫布之間切換,並且具有相同數量的圓,但在不同的畫布中放在畫布上。Android SurfaceView使用線程繪製畫布

我不知道我在做什麼錯,但我不熟悉Treadding,有沒有與我的Android設備有多少核心或類似的東西?

我的代碼如下所示,所以我只使用一個launchthread,它使用一個鏈接到啓動線程的animationthread的佈局文件,並且每秒在畫布上繪製一個圓。 (你可以忽略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> 

而且我有內螺紋類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),它總是最好的說明它,因爲它使得更容易找到bug))。 – RichieHH

回答

4

它似乎應用程序之間切換兩個ca nvasses

是的,這是它是如何工作的。這就是所謂的雙緩衝,你需要重新繪製所有的幀each time

表面的內容不會保留unlockCanvas()和lockCanvas()之間,由於這個原因,表面區域內的每一個像素必須是書面。

因此,您需要將此行canvas.drawColor(Color.BLACK)取消註釋在您的代碼中。

而且您不應該在畫布被鎖定時致電Thread.sleep(1000),否則會導致starvation問題。

+0

好的,謝謝你的回答,所以我需要某種讓我們說ArrayList的地方,我保留我的所有圓對象,然後循環ArrayList繪製方法繪製圓? – randomizer

+0

如果你想每秒鐘添加一個圓圈,並且想要一次繪製所有圓圈,那麼是的,你需要在列表中存儲關於它們的信息,每幀遍歷這個列表並繪製所有的圓圈。 –

+0

好吧thx,現在所有的運行:) – randomizer

0

這聽起來像你有這個工作,但我只是注意到一個小錯誤,我應該指出。

您在未事先調用canvas.save()的情況下調用了canvas.restore()。 來自Canvas的Android開發人員參考:「調用restore()比調用save()更多次是錯誤的。」

我沒有看到任何理由讓您在您的情況下調用canvas.save(),因此您應該刪除對canvas.restore()的調用。

+0

你能幫我一下嗎? http://stackoverflow.com/questions/33909257/canvas-draw-functions-not-working-after-screen-locked-and-unlocked – Jas