2012-10-15 6 views
6

간단한 게임 엔진을 만들기 위해 스레드를 사용하여 캔버스에서 드로잉을 실험하고 있지만 설명 할 수없는 이상한 문제가 있습니다. 이 "게임"의 목적은 매초마다 캔버스에 원을 그리는 것입니다. 이 방법은 작동하지만, 원하는대로 작동하지 않습니다. 앱이 두 캔버스 사이를 전환하고 각 캔버스에 서클을 추가하는 것처럼 보이므로 같은 수의 서클로 매 초 두 캔버스 사이를 전환 할 수 있지만 다른 캔버스로 전환 할 수 있습니다. 캔버스에 놓으십시오.스레드로 드로잉하는 Android SurfaceView 캔버스

내가 뭘 잘못하고 있는지 모르겠지만, Treadding에 익숙하지 않은데, 내 안드로이드 장치의 코어 수와 관련이 있습니까?

내 코드는 아래에 표시되어 있으므로 threadth를 시작하고 매초마다 원을 그리는 animationthread에 연결되는 layoutfile을 사용하는 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); 
    } 
} 

앱이 두 개의 ca 사이를 전환하는 것으로 보입니다. 네바이드

예, 이것이 작동하는 방식입니다. 그것은 더블 버퍼링이라고하며 모든 프레임 each time를 다시 그릴 필요가있다 :

표면의 내용이 unlockCanvas()와 lockCanvas() 사이에 유지되지 않습니다

, 이러한 이유로, 표면 지역 내의 모든 픽셀이어야합니다 쓴.

이 줄은 canvas.drawColor(Color.BLACK)이므로 코드에서 주석을 제거해야합니다.

캔버스가 잠겨있는 동안 Thread.sleep(1000)으로 전화하지 않아야합니다. 그러면 starvation 문제가 발생합니다.

+0

답장을 보내 주셔서 감사합니다. 그래서 모든 서클 오브젝트를 유지 한 다음 Array 클래스를 그리는 방법으로 서클을 그리는 ArrayList를 예로 들어 보겠습니다. – randomizer

+0

매초마다 원을 추가하고 한 번에 모두 그리려면 예를 들어 목록에있는 모든 정보를 저장하고 각 프레임에서이 목록을 탐색하고 모든 원을 그려야합니다. –

+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

관련 문제