Nici z Androidem nie potrafią owinąć mojej głowy projektowaniem

9

Mam problem z pochyleniem głowy nad projektowaniem gry. Na platformie Android mam aktywność i ustawiam widok zawartości na niestandardowy widok powierzchni. Niestandardowy widok powierzchni działa jak mój panel i tworzę instancje wszystkich klas oraz wykonuję wszystkie rysunki i obliczenia.

Pytanie: Czy zamiast tego powinienem tworzyć instancje innych klas w mojej działalności?

Teraz tworzę niestandardową klasę wątków, która obsługuje pętlę gry.

Pytanie: Jak korzystać z tej jednej klasy we wszystkich moich zajęciach? Czy też muszę za każdym razem tworzyć osobne wystąpienie rozszerzonej klasy wątku?

W poprzedniej grze miałem wiele poziomów, które musiały utworzyć instancję klasy wątków, aw klasie wątków musiałem ustawić metody konstruktorów dla każdego oddzielnego poziomu, aw pętli użyć instrukcji switch, aby sprawdzić, który poziom musi renderować i aktualizacja. Przepraszam, jeśli to brzmi myląco.

Chcę tylko wiedzieć, czy metoda, której używam, jest nieefektywna (co prawdopodobnie jest) i jak zacząć projektować ją we właściwy sposób. Przeczytałem wiele samouczków i wciąż mam problemy z tym konkretnym tematem. Może link do niektórych samouczków, które to wyjaśniają? Dzięki.

semajhan
źródło

Odpowiedzi:

13

Gorąco polecam, że masz uczynić wątek (za pomocą Canvas/ OpenGL ES, Canvasto chyba trochę łatwiejsze w instalacji) i nitki gra, w której można umieścić swoją logikę gry.

Aby faktycznie „załadować” grę, możesz stworzyć klasę GameEngine i uczynić ją centralnym punktem aplikacji. Gdy Twój renderer jest gotowy do pracy, możesz utworzyć wywołanie zwrotne do instancji GameEngine, która utworzy i uruchomi dwa wątki przy użyciu Runnabledo renderowania i drugiego Runnabledo logiki gry.

Przykładowy kod:

Rozpoczęcie aplikacji

private GameEngine engine;
private CanvasRenderer renderer;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   // Create instances of your two Runnable classes and pass that into
   // the GameEngine constructor.
   // Create an instance of the game engine.
   engine = new GameEngine(canvasRunnable, gamelogicRunnable);
   renderer = new CanvasRenderer(this, engine); 
   setContentView(renderer); 
}

CanvasRenderer

private GameEngine engine;    

// Save your instance from the GameEngine reference in your constrcutor and make
// a global initializion for your GameEngine instance.  

@Override
public void surfaceCreated(SurfaceHolder holder) {  
   // One time setup here.
   // When your view is ready, make this callback to the 
   // GameEngine.
   engine.surfaceIsReady();
}

Silnik gry

private Thread canvasThread;
private CanvasRunnable canvasRunnable;
// You should be able to figure out how to create a second thread
// where you should put your game logic. :)

// Constructor stuff like creating instances of your threads
// and passing references as you wish to those.
// Don't start the threads here.
// Remember to set references from your Runnable's into your Thread's 
// instances here!

/**
 * Callback. Now your renderer is ready and you
 * can start your threads.
 */
public void surfaceIsReady() {
   thread.setName("Canvas");
   thread.start();
   // Same for game logic.
}
Wroclai
źródło
Wow, dziękuję Podobało mi się, jak to wyjaśniłeś. To jedno wyjaśnienie wyjaśnia mi całą koncepcję.
semajhan
@semajhan: Zapytaj, czy masz więcej problemów. :)
Oto, co mam w głowie: klasa GameEngine, która działa jako „link” lub „odniesienie” do wszystkich innych klas z panelem. Aktywność> Panel> GameEngine> wszystkie pozostałe klasy.
semajhan
@semajhan: Dokładnie. Tylko dla twojej wiedzy: jeśli zdecydujesz się iść z OpenGL ESwami powinni wiedzieć, że w renderer OpenGL ESjuż mieć swój własny wątek i w tym przypadku nie ma potrzeby ręcznego tworzenia i rozpocząć nowy Threadi Runnabledo tego systemu.
Zignoruj ​​ten komentarz.
semajhan
3

Zazwyczaj pętla gry jest zamknięta w jednym działaniu.

po zmianie aktywności wstrzymujesz / zabijasz pętlę gry. Oddzielne działania i tak powinny odpowiadać wstrzymywaniu gry (np. Dlatego, że przełączyłeś się na działanie „wyślij e-mail do znajomych” lub „menu główne”)

Aby uzyskać dodatkowe poziomy, nie powinieneś tworzyć ani przeznaczać nowych wątków ... chyba że przeszedłeś na „ukończenie poziomu, ładowanie następnego poziomu, proszę czekać” Aktywność i będziesz musiał ponownie uruchomić „główną grę” „Aktywność tak czy inaczej. Ale nawet w takim przypadku tak naprawdę nie robisz „dodatkowych” wątków, po prostu tworzysz jeden wątek w tym samym Działaniu, a następnie zabijasz / restartujesz / zabijasz / restartujesz ... itd. za każdym razem, gdy poziom jest ukończony.


źródło
3

Jeśli rozumiesz niemiecki, ten samouczek jest bardzo miły.

W przypadku języka angielskiego mogę polecić ten samouczek

Odnośnie klasy wątków: Nie wiem, czy naprawdę jest konieczne, abyś mógł odwoływać się do wszystkich klas w swojej aplikacji. W mojej grze rozwiązałem to w ten sposób:

Klasa odpowiedzialna za narysowanie głównego GUI ma nadpisaną metodę renderowania. W tej metodzie wywoływana jest klasa wątków, która aktualizuje wszystkie elementy GUI i przetwarza dane wejściowe użytkownika.

Wątek jest również odpowiedzialny za utrzymanie stałej prędkości klatek. W zależności od rozwijanej gry może to być ważne.

RoflcoptrException
źródło
Ten niemiecki tutorial jest fajny, ale został z grubsza przetłumaczony przez vai google, więc trudno go zrozumieć.
semajhan