Gra 2D, część 8: Dobrze mieć wybór... poziomu

25.08.2010 - Marcin Milewski
TrudnośćTrudność

Poziom ukończony? Idziemy do następnego! Ale... dlaczego ma to następować automatycznie? Weźmy sprawy w swoje ręce i zdecydujmy, który poziom jako następny chcemy odwiedzić. Odświeżymy też grafikę, żeby gra była przyjemnością.

Poprzedni artykuł - Diabeł tkwi w szczegółach Następny artykuł - Efektowne przejścia między poziomami

Poniżej możemy zobaczyć efekt prac, które wykonamy w tym artykule:

Animacja wersji końcowej gry.

Czym będziemy się zajmować?

Celem tego artykułu jest przedstawienie sposobu realizacji prostego i wygodnego systemu wyboru poziomu. Określenie kolejnego etapu gry będzie następowało w sposób nieliniowy. Oznacza to, że gracz po przejściu poziomu będzie mógł wybrać kolejny, spośród kilku dostępnych. Inną możliwością będzie cofnięcie się do już rozegranych poziomów. Przykładowe połączenia prezentuje poniższy obrazek:

Graf połączeń między poziomami. Istnienie krawędzi oznacza możliwość przejścia między poziomami.

Pobierz zatem początkowy kod źródłowy do tego artykułu i zaczynamy!

Jak to będzie działać?

Wybieranie poziomów w naszej grze będzie przypominało poruszanie się po grafie połączeń. Wierzchołkami (zwanymi także węzłami) będą u nas poziomy gry, a krawędziami - połączenia między nimi. Oznacza to, że stojąc w którymś z węzłów możemy przemieścić się do innego, z którym jest on połączony bezpośrednią krawędzią. Znajdując się w pewnym wierzchołku będziemy mogli nacisnąć Enter wyrażając w ten sposób chęć zagrania w poziom przypisany do danego węzła.

Zastanówmy się teraz, jakie informacje potrzebujemy przechowywać. Najważniejsze z nich to:

  1. Jakie węzły znajdują się w grafie - każdy węzeł będzie oznaczony kolejnym numerem począwszy od 0. W programie będziemy chcieli przechowywać ich listę (niekoniecznie w sensie dosłownym, ale na tym etapie nie rozważamy jeszcze konkretnego rozwiązania).
  2. Z jakimi wierzchołkami ma połączenia każdy z węzłów, czyli jakie krawędzie zawiera nasz graf połączeń.
  3. Gdzie na ekranie rozmieszczone są poszczególne wierzchołki - będziemy chcieli je przecież rysować. Ponadto jest to informacja niezbędna do poprawnego wyświetlenia krawędzi łączących węzły.
  4. Jaki poziom odpowiada każdemu z wierzchołków - nie chcemy uruchamiać losowego poziomu.

Uwagi dotyczące rozwiązania

Oto kilka uwag, dzięki którym implementowane rozwiązanie będzie nie tylko proste, ale także przyjemne w użytkowaniu:

  1. Połączenia między wierzchołkami będą wyłącznie pionowe oraz poziome. Korzyść, którą otrzymujemy z takiego założenia, to intuicyjny sposób sterowania postacią (np. przy pomocy strzałek).
    Wierzchołki mogą być połączone wyłącznie pionowo lub poziomo.
  2. Przechodzenie postaci między dwoma wierzchołkami będzie odbywało się w sposób płynny. Jeżeli postać znajduje się w którymś z węzłów, to aby wyprawić ją w drogę do innego wierzchołka wystarczy pojedyncze naciśnięcie klawisza (np. strzałki).
  3. Postać będzie mogła zawracać na drodze między wierzchołkami. Punkt ten będzie wymagał nieco uwagi podczas implementowania obsługi wejścia (czyli reakcji na naciśnięte klawisze), ale dzięki niemu interfejs będzie przyjemniejszy w obsłudze.
  4. Zatwierdzenie poziomu, w który chcemy zagrać będzie możliwe wyłącznie wtedy, gdy postać będzie stała w węźle.
  5. Ekran wyboru poziomu powinien zapamiętywać swój stan. Oznacza to przede wszstkim, że po pojawieniu się tego ekranu bohater będzie wyświetlany nad tym polem, z którego uruchomił poziom.

Przyjrzyjmy się bliżej ostatniemu z punktów. Aby go zrealizować, będziemy w klasie Game pamiętać wskaźnik na stan LevelChoiceScreen. Dzięki temu, kiedy uznamy poziom za zakończony, nie będziemy tworzyć nowego stanu LevelChoiceScreen, lecz do m_next_app_state przypiszemy właśnie ten zapamiętany.

Wymaga to od nas dodania metody BindLevelChoiceScreen oraz pola m_level_choice_screen do klasy Game. Dodany kod jest bardzo krótki:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  // Plik Game.cpp
  // (...)
#include "LevelChoiceScreen.h"
  // (...)
void Game::BindLevelChoiceScreen(
  const boost::shared_ptr<LevelChoiceScreen>& screen) {
    m_level_choice_screen = screen;
}
 
      
  // Plik Game.h
  // (...)
  // dołączenie nagłówków
  // (...)
 
class LevelChoiceScreen;
 
  // publiczna metoda
    void BindLevelChoiceScreen(
      const boost::shared_ptr<LevelChoiceScreen>& screen);
 
  // prywatne pole
    boost::shared_ptr<LevelChoiceScreen> m_level_choice_screen;
  
0
Twoja ocena: Brak

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com