Gra 2D, część 12: Edytor poziomów cz. 2
15.03.2011 - Marcin Milewski
Przedstawienie pędzlaZanim jednak przejdziemy do uaktualnienia klasy Editor, wyjaśnijmy, czym jest pędzel. Po raz pierwszy pojawił się w poprzednim artykule, a w tym wykorzystaliśmy go podczas tworzenia specjalnej kontroli. Otóż, pędzel ten ma takie samo zadanie jak w edytorze grafiki. To znaczy, że wybieramy pędzel z podręcznej palety, a następnie nim rysujemy. W naszym edytorze będzie dokładnie tak samo. Dokonamy jednak pewnego uproszczenia i uznamy gumkę za specjalny rodzaj pędzla. Pędzle w naszym edytorze dzielimy na 3 rodzaje:
Elementy dodawane przez konkretne rodzaje pędzli.
a) Pędzel do dodawania pól; b) Pędzel do dodawania jednostek; c) Pędzel do zadań specjalnych Pędzel będzie przechowywał (można o tym myśleć w kategorii opakowania -- pędzel opakowuje sprite'a) instancję klasy Sprite. Obiekt zawierający instancję typu Brush będzie mógł ją odpytać o posiadany obrazek, a następnie wykorzystać go do własnych celów. Zwykle oznacza to, iż sprawdzi on jakiego obiektu reprezentacją jest sprite, a następnie doda opis odpowiedniego elementu do poziomu, który potem zostanie zapisany do pliku lvl lub ents. Zauważ, że ten mechanizm jest bardziej ogólny niż przedstawione tu zastosowanie. Poniżej znajduje się implementacja omawianej klasy. Dla skrócenia kodu wszystkie trzy typy pędzla są reprezentowane przez tę samą klasę. W przypadku rozwoju gry o kolejne rodzaje pędzli, jest to dobre miejsce, żeby poćwiczyć refaktoryzację kodu. Oto kod klasy Brush:
W celu ułatwienia tworzenia instancji tej klasy, dodamy metody statyczne tworzące każdy z typów pędzla. Nazywamy je New, sugerując tym samym, że zwrócony zostanie wskaźnik (w naszym przypadku inteligentny wskaźnik, bo takimi się posługujemy), a nie obiekt klasy Brush. Poniższy kod powinien znaleźć się w sekcji publicznej tej klasy.
Korzystanie z takich statycznych metod jest bardzo wygodne, jeżeli często tworzymy wskaźniki na obiekty. Bez nich, pisalibyśmy:
Dzięki nim możemy napisać krótszy i lepiej oddającą intencje programisty następujący kod:
Upgrade klasy EditorUtworzyliśmy już kompletny mechanizm obsługujący graficzny interfejs użytkownika. W naszym edytorze użytkownik może w prosty sposób wybrać, gdzie i jaki element (jednostka, bonus, przeciwnik, pole planszy,...) chce dodać do poziomu. Umieszczenie nowego obiektu odbywa się poprzez kliknięcie myszką. Aby jednak odniosło swój skutek, sterowanie w aplikacji musi dotrzeć w odpowiednie miejsce kodu obsługującego GUI. Dlatego też swoje kroki kierujemy teraz w stronę integracji systemu GUI z dotychczas rozwiniętym edytorem. Pierwszym polem jakie należy dodać jest wskaźnik (oczywiście inteligentny) na klasę bazową Gui. To właśnie do niej klasa Editor będzie przekazywała m.in. komunikaty z urządzeń wejścia. Będzie to możliwe jedynie wtedy gdy GUI będzie prezentowane na ekranie. Aby obsłużyć pokazywanie i ukrywanie graficznego interfejsu użytkownika dodajemy pole (nazywane czasem flagą lub znacznikiem ze względu na swój charakter, czyli możliwość przyjęcia tylko jednej z dwóch wartości) m_is_gui_visible. Konstruktor klasy Editor prezentuje się teraz następująco:
Nowe (prywatne) pola tej klasy:
Publiczne metody do włączania/wyłączania oraz odpytywania GUI o widoczność:
Jak już wspominaliśmy przy okazji prezentacji pędzla, może być on jednego z trzech rodzajów, co związane jest z akcją zleconą przez użytkownika:
Poniżej znajduje się kod usprawniający sprawdzanie, czy wskazany tryb jest aktualnie aktywny. Są to metody publiczne.
Ostatnią metodą, która będzie przydatna podczas implementacji nowych funkcjonalności jest ShouldSnapToGrid. Będzie ona odpowiadać "tak", gdy dodawany element powinien zostać wyrównany do (niewidzialnej) siatki, oraz "nie" w przeciwnym razie. Pierwszą wartość będzie zwracała przede wszystkim dla pól planszy. Będzie to jednak właściwe miejsce na dodanie kolejnych "wyjątków", na przykład jeżeli zażyczymy sobie, aby trzymanie klawisza "CTRL" wymuszało takie zachowanie edytora. Poniżej znajduje się prosta deklaracje omówionej metody:
|
Copyright © 2008-2010 Wrocławski Portal Informatyczny
design: rafalpolito.com