Thursday, September 16, 2010

Stany (nie do końca zjednoczone)

Środowisko do testów właściwie gotowe, więc można dłubać dalej. Poniżej postaram się przybliżyć odrobinę o co chodzi z tymi stanami gry i dlaczego warto stosować takie podejście.

Bardzo popularne w grach są różnego rodzaju intra. Np. najprostsze to wyświetlenie przez jakiś czas logo producenta gry. Następnie pojawia się na ogół główne menu gry. Po wybraniu "start/nowa gra" rozpoczyna się gra. To co wymieniłem to właśnie stany gry. Czy można się bez nich obejść, tzn. bez definiowania oddzielnych klas do ich obsługi? Oczywiście, że można, ale czy nie lepiej mieć porządek w kodzie i wszytko ładnie logicznie podzielone?

Jak to wygląda w praktyce?

W kasuroid zdefiniowałem klasę bazową dla stanów gry tj. GameState (tak, State wrócił do pierwotnej nazwy). Posiada ona następujące metody:
  • init()
  • term()
  • pause()
  • resume()
  • update()
  • render()
Powyższe metody oznaczone są jako final i nie mogą być przeciążone przez klasy pochodne. Zdecydowałem się na takie podejście, aby zapewnić wewnętrzna kontrolę stanu. Np. wywołanie update, gdy obiekt nie jest zainicjalizowany wygeneruje błąd. Można jednak przeciążyć metody, które będą wołane w odpowiednich stanach tj.:
  • onInit()
  • onTerm()
  • onPause()
  • onResume()
  • onUpdate()
  • onRender()
Zarządzanie stanami gry zrealizowałem w oparciu o stos (mGameStatesStack w Core). Core posiada interfejs do zarządzania stanami, a mianowicie:
  • changeState(GameState gameState) - czyści stos, po czym wrzuca na niego gameState
  • pushState(GameState gameState) - pauzuje aktualnie znajdujący się na szczycie stosu stan i dodaje gameState
  • popState() - zdejmuje ze stosu aktualny stan i włącza (resume) stan następny
Jest to chyba najprostszy sposób realizacji zarządzania stanami gry. Można jednak przy jego pomocy realizować całkiem ciekawe przejścia w grze (co też zamierzam w odpowiednim czasie pokazać).

Ok, czas na pierwszy oficjalny test :) Dodałem nowy pakiet do projektu: com.kasuroid.test.cases. Do tego pakietu mam zamiar wrzucać wszystkie testowe activity wraz z potrzebnymi klasami. Aby mieć w miarę porządek i jako, że pojedynczy test może składać się z wielu plików, pakiet com.kasuroid.test.cases będę dzielić na drobne "podpakiety". Pierwszy podpakiet to GameStates. Stworzyłem grupę "Game states" i zdefiniowałem TestCaseGameStateActivity oraz dwa "stany gry": TestCaseGameStateState1, TestCaseGameStateState2. Aby zainicjować pierwszy stan wystarczy wywołać change state w activity:
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        
        Core.getInstance().changeState(new TestCaseGameStateState1());
    } 
Gdy jesteśmy w stanie 1 (aktywny TestCaseGameStateState1) i naciśniemy dowolny klawisz to przejdziemy do stanu 2 (TestCaseGameStateState2). Jeśli zostanie naciśnięty klawisz w stanie 2 to nastąpi powrót do stanu 1. Wyjść z programu można w dowolnym momencie klikając na ekran.

Stan 1:
Stan 2:
Kliknięcie na ekran powoduje wyjście z testu:
Aby lepiej zobaczyć jak zachowują się poszczególne elementy kasuroid proponuję uruchomić projekt i podejrzeć logi (próbowałem przekleić chociaż część logów, ale poszczególne wiersze nie mieszczą się w jednej linii, a mi nie bardzo chce się ich ręcznie ciąć :P).

Dobrej nocy!

No comments:

Post a Comment