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?
Forse rilevanti: http://stackoverflow.com/questions/21567641/ dovrebbe-the-renderingthread-of-a-surfaceview-have-the-same-cycle-as-the-view/21684399 # 21684399 – fadden