Platformówka - jak to się robi?
24.11.2009 - Marcin Milewski
![]() ![]() Rysujemy trójkątNadszedł czas aby wyświetlić coś więcej niż czarne okienko. Zobaczmy jak łatwe jest wyświetlenie trójkąta: podajemy współrzędne trzech jego wierzchołków oraz składowe koloru, a OpenGL zrobi za nas resztę.
Warto zaznaczyć, że kolejność, w której podane zostały wierzchołki, nie jest przypadkowa - jest to kierunek przeciwny do ruchu wskazówek zegara (ang. CCW - Counter ClockWise). Oto efekt działania stworzonego do tej pory kodu: ![]() Jeśli zmienimy rozmiar okna, trójkąt zmienia się razem z nim (kąty nie zostają zachowane). A jak sprawić, żeby trójkąt skalował się proporcjonalnie? Jak stworzyć trójkąt, który zawsze będzie wyśrodkowany na ekranie? Pokaż/ukryj odpowiedźProblem występuje, gdy zmienimy rozmiar okna tylko w jednym kierunku, lub gdy zmienimy rozmiar w obu kierunkach, ale nierównomiernie. Zależy nam, aby stosunek szerokości do wysokości obszaru, po którym rysujemy, był stały. Można zatem zmodyfikować rozmiar tego obszaru, albo wyliczać współrzędne wierzchołków trójkąta na podstawie wspomnianego stosunku - w zależności od efektu, który chcemy osiągnąć. Animacja oparta na sprite'achDo tworzenia grafiki w grach 2D najczęściej wykorzystuje się sprite'y, które - odpowiednio zestawione - tworzą wygląd gry. Sprite (z ang. duszek) to po prostu dwuwymiarowy obrazek wyświetlany na ekranie. Jest on graficzną reprezentacją podłoża, jak również postaci sterowanej przez gracza bądź komputer. Można również w ten sposób przygotować całą animację czy czcionkę, która będzie wykorzystywana w grze. Główną zaletą gier opartych na sprite'ach jest ich małe zapotrzebowanie na moc obliczeniową do wyświetlenia grafiki. Sprite'y przygotowywane są w programach pozwalających tworzyć i edytować grafikę rastrową, wektorową, czy nawet - trójwymiarową. Następnie zapisywane są jako sekwencja obrazków. Ze względów (przede wszystkim) wydajnościowych umieszcza się wiele pojedynczych obrazków w jednym dużym, tworząc w ten sposób tzw. atlas. Sprite'y nie są oczywiście pozbawione wad, związanych głównie z tym, że używamy grafiki rastrowej. Tak przygotowane obrazy nie nadają się do powiększania, gdyż prowadzi to do powstania artefaktów. Kolejnym problemem jest brak możliwości interpolacji, czyli płynnego przejścia, między dwoma obrazkami (np. klatkami animacji). Te problemy można rozwiązać na wiele sposobów, jednak nie będziemy się tym zajmować. W grze przyjmiemy kilka założeń dotyczących sprite'ów:
Odczytywanie informacji o sprite'achPrzejdźmy teraz do sposobu przechowywania informacji o tym, gdzie w atlasie należy szukać konkretnych sprite'ów. Oto informacje, które musimy znać dla każdej animacji (niektóre animacje są jednoklatkowe):
Na potrzeby gry uprościmy sposób dostarczania danych i nie będziemy ich ładować z pliku, lecz będą one od razu przechowywane w odpowiednim kontenerze. Struktura przechowująca informacje o sprite'cie przedstawia się następująco:
Potrzebujemy jeszcze klasy, która będzie zajmowała się ładowaniem tych danych oraz ewentualnym informowaniem, że żądane dane nie są dostępne. Do gromadzenia danych wykorzystamy standardowy kontener map. Oto definicja klasy SpriteConfig:
Wyjaśnienia wymaga na pewno ostatnia linijka na powyższym listingu. Zdefiniowaliśmy w niej shared pointer dla klasy SpriteConfig, aby skrócić zapis. W grze będziemy wykorzystywać mechanizm shared pointerów w miejscach, gdzie można by użyć zwykłych wskaźników. Unikniemy w ten sposób niepotrzebnych problemów ze zwalnianiem pamięci, gdyż te wskaźniki zwolnią się same, gdy już nie będą potrzebne. Implementacja metod powyższej klasy jest bardzo prosta: Pokaż/ukryj kod
Obiekty tworzone w konstruktorze klasy SpriteConfig definiują animacje na poniższym obrazku. Punkt (0,0) umieszony jest w lewym górnym rogu, a punkt (1,1) - w prawym dolnym. Szerokość i wysokość sprite'a określamy w pikselach. ![]() (7 ocen) |
Copyright © 2008-2010 Wrocławski Portal Informatyczny
design: rafalpolito.com