2010-10-30 13 views
15

Sto usando un SurfaceView e un thread di rendering per sviluppare un gioco basato su struttura come LunarLander.Programmazione con SurfaceView e strategia di thread per lo sviluppo del gioco

Tuttavia, ho affrontato molti problemi, e qui voglio indicarli tutti. Vorrei che chiunque voglia sviluppare un gioco non debba più lottare con loro. E chiunque abbia una migliore idea della struttura può condividere le loro esperienze, perché io sono ancora nuovo ad Android ed è impaziente di imparare :)

[1] La funzione thread.start() non deve essere chiamata più di una volta.

Molti articoli menzionati per creare un thread quando viene creato superficie, al fine di rendere nuovamente dopo l'attività pausa utilizzando il metodo:

public void surfaceCreated(SurfaceHolder holder) { 
    // start the thread here so that we don't busy-wait in run() 
    // waiting for the surface to be created 
    if (thread.getState() == Thread.State.TERMINATED) 
    { 
     thread = new LunarThread(getHolder(), getContext(), getHandler()); 
    } 
    thread.setRunning(true); 
    thread.start(); 
} 

Si può vedere che se il filo non è terminato e la funzione è chiamato, l'attività si blocca.

[2] Se si preme il tasto "power" o "red phone" o il telefono è inattivo per alcuni minuti, l'attività sarà onPause(), ma il thread è ancora in esecuzione. Questa è una pessima pratica, quindi ho bisogno di trovare un metodo per fermare il thread e ricominciare da capo quando onResume().

[3] Se il blocco dello schermo è verticale/orizzontale e il gioco è attaccato all'altro orientamento, il blocco dello schermo ti ha obbligato a "orientare" una volta. Ciò significa ricominciare l'attività. Non riesco ancora a trovare una soluzione. (Come ho già detto in Android screen orientation bug)

Ecco il mio codice per risolvere questi problemi:

UIThread

public class UIThread extends Activity 
{ 
    private gameView gameview; 
    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     gameview = (gameView) findViewById(R.id.gameview); 
    } 
    protected void onPause() 
    { 
     super.onPause(); 
     Log.v("MY_ACTIVITY", "onPause"); 
     gameview.terminateThread(); 
     System.gc(); 
    } 
    protected void onResume() 
    { 
     super.onResume(); 
     Log.v("MY_ACTIVITY", "onResume"); 
     if (gameview.surfaceCreated == true) 
     { 
      gameview.createThread(gameview.getHolder()); 
     } 
    } 
} 

GameView

public class gameView extends SurfaceView implements SurfaceHolder.Callback 
{ 
    boolean surfaceCreated; 
    class gameThread extends Thread{} 
    public gameView(Context context, AttributeSet attrs) 
    { 
     super(context, attrs);context.getResources(); 
      Log.v("MY_ACTIVITY", "gameView"); 
     surfaceCreated = false; 
    } 
    public void createThread (SurfaceHolder holder) 
    { 
      thread = new gameThread(holder); 
     thread.run = true; 
     thread.start(); 
    } 
    public void terminateThread() 
    { 
     thread.run = false; 
     try 
     { 
      thread.join(); 
     } 
     catch (InterruptedException e) 
     { 
      Log.e("FUNCTION", "terminateThread corrupts"); 
     }  
    } 
    public void surfaceCreated(SurfaceHolder holder) 
    { 
     Log.v("MY_ACTIVITY", "surfaceCreated"); 
     if (surfaceCreated == false) 
     { 
      createThread(holder); 
      surfaceCreated = true; 
     } 
    } 
    public void surfaceDestroyed(SurfaceHolder holder) 
    { 
     Log.v("MY_ACTIVITY", "surfaceDestroyed"); 
     surfaceCreated = false; 
    } 
} 

manifesto

<activity android:name=".UIThread" 
      android:screenOrientation="landscape" 
      android:configChanges="orientation"> 

Io uso onResume() anziché surfaceCreated() nella nuova discussione. E ho impostato un valore booleanoper sapere che onResume() proviene dalla prima volta che l'applicazione è stata creata o proviene dalla situazione di "disattivazione schermo".

Quindi il thread muore ogni volta che viene chiamato onPause(). Sembra essere una buona pratica. Un altro modo per interrompere il thread e riprendere di nuovo è sincronizzare un oggetto e chiamare wait/notify. Ma io non so che è meglio o no.

C'è un modo migliore per controllare il thread di rendering?

+0

Forse rilevanti: http://stackoverflow.com/questions/21567641/ dovrebbe-the-renderingthread-of-a-surfaceview-have-the-same-cycle-as-the-view/21684399 # 21684399 – fadden

risposta

1

Ho avuto a che fare con lo stesso problema. Sto imparando lo sviluppo di giochi su Android e ho anche basato il mio primo progetto sull'esempio di Lunar Lander. Ho scoperto che il progetto SpriteMethodTest creato da Chris Pruett implementa un approccio molto migliore in termini di gestione dei thread. Si tratta di utilizzare i metodi di notifica e attesa, però. Non saprei dire se è meglio della tua soluzione o no.

3

la soluzione è qui

public void surfaceCreated(SurfaceHolder holder){ 

      if (plot_thread.getState() == Thread.State.TERMINATED) { 
       plot_thread = new WaveformPlotThread(getHolder(), this); 
       plot_thread.setRunning(true); 
       plot_thread.start(); 
      } 
      else { 
       plot_thread.setRunning(true); 
       plot_thread.start(); 
      } 
     } 
3

spero che possa aiutare

@Override 
public void surfaceCreated(SurfaceHolder holder) { 

    //if it is the first time the thread starts 
    if(thread.getState() == Thread.State.NEW){ 
    thread.setRunning(true);//riga originale 
    thread.start();//riga originale 
    } 

    //after a pause it starts the thread again 
    else 
    if (thread.getState() == Thread.State.TERMINATED){ 
     thread = new MainThread(getHolder(), this); 
     thread.setRunning(true); 
     thread.start(); // Start a new thread 
     } 
    } 

e questo

@Override 
    protected void onPause() { 
    Log.d(TAG, "Pausing..."); 
    MainThread.running=false;//this is the value for stop the loop in the run() 
    super.onPause(); 
    } 
+0

Boris grazie mille per la vostra risposta è semplice e funziona dopo lunghe giornate di ricerca. –

+0

Ho usato questo codice. Il mio problema in alcuni dispositivi è che la superficie richiede tempo per essere creata; qualche secondo. Qualche soluzione? –

Problemi correlati