2012-10-15 13 views
6

Sto sperimentando il disegno su una tela utilizzando una discussione per creare un motore di gioco semplice ma ho alcuni problemi strani che non riesco a spiegare. Lo scopo di questo "gioco" è disegnare un cerchio ogni secondo sulla tela. Funziona, ma non nel modo in cui voglio che funzioni, sembra che l'app passi da due tele all'altra e aggiunga un cerchio a ogni tela in modo da ottenere un passaggio tra due tele ogni secondo con lo stesso numero di cerchi ma in un altro posto sulla tela.Disegno su superficie SurfaceView per Android con una filettatura

Non so cosa sto facendo male, ma non sono così familiare con Treadding, ha qualcosa a che fare con quanti core ha il mio dispositivo Android o qualcosa del genere?

Il mio codice è mostrato di seguito, quindi uso solo un launchthread che utilizza un file di layout che si collega al tema dell'animazione che avvia una discussione e disegna un cerchio sulla tela ogni secondo. (Puoi ignorare il touchevent, non è ancora usato).

Il progetto esiste fuori da un launchthread principale:

public class MainActivity extends Activity { 

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

che utilizza questo file di layout:

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

E mia classe SurfaceView con una classe filettatura interna:

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

Dovrebbe essere AnimationView2 nel codice? Una versione corretta sarebbe apprezzata. – RichieHH

+0

(ps quando copi il codice da un esempio di esempio (questo è un LunarLander leggermente modificato) è sempre meglio indicarlo in quanto rende più facile la caccia agli insetti)). – RichieHH

risposta

4

sembra che l'app passi tra due ca nvasses

Sì, è così che funziona. Si chiama il doppio buffering e avete bisogno di ridisegnare tutta la cornice each time:

Il contenuto della superficie non viene mai conservato tra unlockCanvas() e lockCanvas(), per questo motivo, ogni pixel all'interno dell'area di superficie deve essere scritto.

Quindi è necessario che questa riga canvas.drawColor(Color.BLACK) sia decommentata nel codice.

E non si dovrebbe chiamare Thread.sleep(1000) mentre il canvas è bloccato, causerà il problema starvation.

+0

Ok, grazie per la tua risposta, quindi ho bisogno di una sorta di ArrayList dove tengo tutti gli oggetti del mio cerchio e poi faccio un ciclo di ArrayList nel metodo draw per disegnare i cerchi? – randomizer

+0

Se si desidera aggiungere una cerchia ogni secondo e si desidera disegnare tutti in una volta allora sì, è necessario memorizzare le informazioni su tutti loro in lista, attraversare questo elenco ogni fotogramma e disegnare tutte le cerchie. –

+0

Ok thx, ho tutto a posto ora :) – randomizer

0

Sembra che tu abbia funzionato, ma ho appena notato un piccolo errore che dovrei sottolineare.

Hai chiamato canvas.restore() senza chiamare canvas.save() in anticipo. Dal riferimento dello sviluppatore Android per Canvas: "È un errore chiamare call restore() più volte che save() è stato chiamato."

Non vedo alcun motivo per chiamare canvas.save() nel tuo caso, quindi è necessario rimuovere la chiamata a canvas.restore().

+0

Puoi aiutarmi per favore con questo? http://stackoverflow.com/questions/33909257/canvas-draw-functions-not-working-after-screen-locked-and-unlocked – Jas

Problemi correlati