2010-10-30 11 views
15

Używam SurfaceView i wątku renderowania do opracowania gry opartej na strukturze takiej jak LunarLander.Programowanie za pomocą SurfaceView i strategii wątków dla tworzenia gier

Jednak stanąłem w obliczu wielu problemów i tutaj chcę je wszystkie wskazać. Chciałbym, aby każdy, kto chce rozwinąć grę, nie musiał już z nią walczyć. I każdy, kto ma lepszy pomysł na strukturę, może dzielić się swoimi doświadczeniami, ponieważ wciąż jestem nowicjuszem dla Androida i chcę się uczyć :)

[1] Funkcja thread.start() nie powinna być wywoływana więcej niż jeden raz.

Wiele artykułów wymienionych stworzyć wątek, gdy powierzchnia jest stworzony, aby ponownie uczynić po aktywność wstrzymana za pomocą metody:

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(); 
} 

Widać, że jeśli wątek nie jest zakończona, a funkcja ta jest wywoływane, działanie ulega awarii.

[2] Jeśli naciśniesz przycisk "zasilanie" lub "czerwony telefon" lub telefon będzie nieaktywny przez kilka minut, aktywność będzie wynosić onPause(), ale wątek nadal działa. To jest naprawdę zła praktyka, więc muszę znaleźć sposób na zatrzymanie wątku i zacząć od nowa, gdy onResume().

[3] Jeśli blokada ekranu jest ustawiona pionowo/pozioma, a twoja gra jest naklejona na inną orientację, blokada ekranu zmusiła Cię do "orientowania" raz. Oznacza to, że chcesz rozpocząć działanie jeszcze raz. Nadal nie mogę znaleźć rozwiązania. (Jak wspomniano w Android screen orientation bug)

Oto mój kod, aby rozwiązać te problemy:

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; 
    } 
} 

Oczywisty

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

Używam onResume() zamiast surfaceCreated() do nowego wątku. I ustawiłem boolean surfaceCreated, aby wiedzieć, że onResume() pochodzi z pierwszej aplikacji lub pochodzi z "wyłączenia ekranu".

Wątek umiera za każdym razem, gdy wywoływana jest nazwa onPause(). Wydaje się być dobrą praktyką. Innym sposobem na zatrzymanie wątku i ponowne wznowienie jest synchronizacja obiektu i wywołanie oczekiwania/powiadomienie. Ale nie wiem, czy to lepiej, czy nie.

Czy istnieje lepszy sposób kontrolowania wątku renderowania?

+0

Ewentualnie istotne: http://stackoverflow.com/questions/21567641/ powinieneśponownieprzeczytać-widok-powierzchni-mieć-ten-sam-cykl-jak-widzenia-/ 21684399 # 21684399 – fadden

Odpowiedz

1

Zajmuję się tym samym problemem. Uczę się programowania gier na Androida i opieram swój pierwszy projekt na przykładzie Lunar Lander. Odkryłem, że projekt SpriteMethodTest stworzony przez Chrisa Pruetta wdraża znacznie lepsze podejście do zarządzania wątkami. Chodzi jednak o używanie metod powiadomień i czekania. Nie mogłem stwierdzić, czy jest lepszy od twojego rozwiązania, czy nie.

3

rozwiązaniem jest tutaj

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

Mam nadzieję, że to może pomóc

@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 
     } 
    } 

i to

@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

Borys wielkie dzięki za twoją odpowiedź r jest prosty i działa po długich dniach poszukiwań. –

+0

Użyłem tego kodu. Mój problem w niektórych urządzeniach polega na tym, że powierzchnia wymaga czasu; trochę sekundy. Jakieś rozwiązania? –

Powiązane problemy