2012-10-15 17 views
6

Eksperymentuję z rysowaniem na płótnie za pomocą wątku, aby stworzyć prosty silnik gry, ale mam pewne dziwne problemy, których nie potrafię wyjaśnić. Celem tej "gry" jest narysowanie okręgu co sekundę na płótnie. To działa, ale nie w taki sposób, w jaki chcę, żeby działało. Wygląda na to, że aplikacja przełącza się między dwiema płótnami i dodaje koło do każdego płótna, dzięki czemu można przełączać się między dwiema płótnami w każdej sekundzie z taką samą liczbą okręgów, ale w innym umieścić na płótnie.Rysunek na płótnie Android SurfaceView z gwintem

Nie wiem, co robię źle, ale nie jestem zaznajomiony z Treadding, ma to coś wspólnego z tym, ile rdzeni ma moje urządzenie z Androidem czy coś takiego?

Mój kod jest pokazany poniżej, więc po prostu używam launchthread, który używa pliku layoutfile, który łączy się z animacją, która rozpoczyna wątek i rysuje okrąg na płótnie co sekundę. (Możesz zignorować touchevent, nie używa go jeszcze).

Projekt występuje z głównego launchthread:

public class MainActivity extends Activity { 

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

który korzysta z tego pliku układ:

<?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> 

i moja klasa Surfaceview z wewnętrzną klasy Temat:

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

Czy to powinien być AnimationView2 w kodzie? Poprawiona wersja byłaby doceniona. – RichieHH

+0

(ps, gdy kopiujesz kod z przykładowego przykładu (jest to lekko zmodyfikowany LunarLander), zawsze najlepiej jest go wypowiadać, ponieważ ułatwia polowanie na robaki)). – RichieHH

Odpowiedz

4

Wygląda na to, że aplikacja przełącza się między dwoma ca nvasses

Tak, tak to działa. To się nazywa podwójne buforowanie i trzeba przerysować całą ramkę each time:

Zawartość Surface nie jest zachowana pomiędzy unlockCanvas() i lockCanvas(), z tego powodu, każdy piksel wewnątrz powierzchnia musi być pisemny.

Potrzebujesz tej linii canvas.drawColor(Color.BLACK), aby odkomentować kod.

Nie powinieneś dzwonić pod numer Thread.sleep(1000), gdy płótno jest zablokowane, spowoduje to problem z numerem starvation.

+0

OK, dziękuję za odpowiedź, więc potrzebuję jakiegoś powiedzmy ArrayList, gdzie trzymam wszystkie moje obiekty w okręgu, a następnie zapętlam ArrayList w metodzie rysowania, aby narysować kółka? – randomizer

+0

Jeśli chcesz dodać kółko co sekundę i chcesz narysować wszystkie naraz, a następnie tak, musisz przechowywać informacje o wszystkich z nich na liście, przechodzić tę listę po każdej klatce i rysować wszystkie kółka. –

+0

Ok thx, wszystko już działa :) – randomizer

0

Wygląda na to, że to działa, ale zauważyłem mały błąd, który powinienem wskazać.

Nazwałeś canvas.restore() bez uprzedniego wywołania canvas.save(). Od dewelopera systemu Android dla Canvas: "Błędem jest wywoływanie funkcji restore() więcej razy niż wywołano metodę save()."

Nie widzę żadnego powodu, aby wywołać w twoim przypadku canvas.save(), dlatego powinieneś usunąć wywołanie canvas canvas.restore().

+0

Czy możesz mi pomóc z tym? http://stackoverflow.com/questions/33909257/canvas-draw-functions-not-working-after-screen-locked-and-unlocked – Jas

Powiązane problemy