MAPA ŚWIATA 2D

Ponownie witam wszystkich sympatyków OMEGI, ortodoksyjnych DELPHI-arzy jaki i tych co mają uraz do C. Czyli swoistego tłumaczenia wielu rozwiązań zapisanych w C na Pascala…

O czym będzie mowa w tej części?

Ano… o bardzo prostym pomyśle utworzenia pomniejszonego widoku świat 2D tak jak jest to widoczne na powyższym rysunku. Na mapie widoczny jest:

  1. świat 2D (bardzo odkrywcze 🙂
  2. żółty punkt odpowiadający położeniu gracza (związany jest z ruchem gracza)
  3. biały prostokąt odpowiadający obszarowi widocznej części świata (związany jest z ruchem żółtego punktu)
  4. czerwony prostokąt rysowany wokół punktu wskazanego lewym przyciskiem mychy (prawy go niszczy)

Cały kod omawiane klasy mapy(nie licząc deklaracji jej typu) zajmuje około 40 linijek i jest zapisany w pliku: OmegaMap.pas. Podaną klasę można oczywiście sobie rozbudować lub przerobić ją w komponent…

Uwagi związane z tworzeniem widoków mapy

Nasza mapa będzie potomkiem klasy TOmegaSurface. Oczywiści można to sobie zrobić przy pomocy wyświetlania rysunku bezpośrednio z OmegaImageList lub w inny sposób. Ja wybrałem takie rozwiązanie bo:

  • tworząc odrębną klasę ma się większy porządek w głównym kodzie programu
  • wprowadzenie ewentualnych poprawek odbywa się w pliku klasy a nie w głównym kodzie
  • można łatwo utworzyć kilka potomków (pamiętajcie grozi nam niż demograficzny…)

Ponadto mapę wyświetlam w całości. Oczywiście wcześniej trzeba sobie ją jakimś innym własnym programikiem utworzyć, przeskalować i zapisać do pliku. Chyba ze ktoś się uprze i w czasie rzeczywistym będzie rysować kolejno kafle świata 2D w odpowiednim pomniejszeniu. Ale należ pamiętać, że trzeba to zrobić co najmniej dla 2 warstw. Z prostego rachunku wnika, że będzie tego znaczna ilość. Przykład świat ma rozmiar 125×75 co dla dwóch warstw da 2x125x75=18750 operacji skalowania i 18750 operacji rysowania kafli. Chyba, że przeskalujemy sobie kafle wcześniej i załadujemy je do OmegImageLis to zostanie nam tylko 18750 operacji rysowania….Tak czy siak zawsze to pochłonie trochę czasu.

Nasza klas będzie sobie gotową mapkę pobierać z zasobu

Co zyskujemy z takiego rozwiązania?

Możemy bardzo szybko zmieniać mapę świata poprzez zmianę indeksu wycinanej klatki lub zmianę indeksu całego obrazu mapy. Kiedy tak zmiana może wystąpić? W tedy gdy przechodzimy do innego poziomu gry lub na przykład w obrębie jednego poziomu istnieje kilka równoległych światów. Moje obrazy map świata 2D zgadzają się tylko co do układu dróg i położenia karczmy. A to tylko da tego, że za każdym uruchomieniem programu pozycje drzew są losowane. Wniosek: najlepiej cały świat jest budować sobie w edytorze.

Jakie zadania wykonuje nasz klasa naszej mapy?

  • na bieżąco rysuje położenie gracza
  • rysuje prostokąt widocznego obszaru świata 2D
  • reaguje na kliknięcie lewym/ prawym przyciskiem myszki
  • mapa nie jest rysowana gdy gracz jest w karczmie

Co można dodać do klasy?

  • położenia innych żywych obiektów
  • przesuwanie świata 2D do wskazanego punktu kliknięcja w mapie (podobnie jak to zrobiłem w swoim edytorze światów 2D patrz www.delphi.ilion.pl lub jak to jest zrobione w profesjonalnych grach)
  • ukrycie miejsc w których nie było jeszcze duszka gracza
  • i wiele, wiele innych pomysłów

Jak utworzyć i wywołać naszą mapę w projekcie gry?

Tu omówię tylko nagłówki procedur i miejsce ich wywołania. Analizę kodu pozostawiam czytelnikowi.

  1. Miejsce i sposób tworzenia mapy

Jak widać w 5 liniach mamy utworzoną naszą mapę. Tu chciałbym zwrócić uwagę na prametry podawane do procedury Mapa.UstawParametr:

  • 11 (parametr AIdObraz) to indeks obrazu map przechowywanych w OmegaImageList1
  • 3 (parametr AidKlatka)to indeks wycinanej klatki mapy
  • 0 (parametr ALeft) to współrzędna X lewego górnego rogu zaczepienia mapy
  • OmegaScreen1.Height-OmegaImageList1.ImageList.Items[11].TileHeight (parametr ATop) to współrzędna Y lewego górnego rogu zaczepienia mapy
  • 12 (parametr ARectCol) to liczba klatek widocznego świata w osi X , tu odpowiada wartości 800 div 64
  • 18 (parametr ARectRow) to liczba klatek widocznego świata w osi Y , tu odpowiada wartości 600 div 32
  • 64 (parametr AKlakaMapyWidth) to szerokość kafla siatki mapy
  • 32 (parametr AKlakaMapyHeight) to wysokość kafla siatki mapy

Deklaracja nagłówka tej procedury:

Skoro już utworzyliśmy mapę to należy ją wyświetlić i śledzić ruch gracza. I zrobimy to w procedurze zegara gry. Czyli tak:

W procedurze Mapa.Ruch pojawia się liczba 8. Ta liczba jest wynikiem umiejscowienia rogu mapy w obrazie klatki mapy (brzmi jak masło maślane…) Zobrazuję to tym rysunkiem:

Ciała procedury Mapa.Draw nie będę tu przytaczać. Jest ona bardzo prosta. Jej zadanie polega na rysowaniu obrazu wycinanej klatki mapy, rysowaniu żółtego prostokąta pozycji gracza jak i białego. W celach poglądowych umieściłem również zaznaczenie czerwoną ramkę obszaru klikniecia myszki w mapie. Procedura Mapa.MauseDawn jest wywołana w procedurze formatki TForm1.FormMouseDown.

No cóż prawdopodobnie jest to ostatni art z cyklu wędrówek w świecie 2D…Na pewno nie wyczerpuje to problemów i pomysłów na stworzenie gry 2D w oparciu o komponent OMEGI, ale dalsze ciągnięcie tematu w kolejnych częściach mija się z celem.

Pytanie dlaczego?

Dlatego gdyż nie potrzebnie rozbudowuje się kod z każdą nową częścią. A to utrudnia jego analizę. Lepiej jest rozważać modele rozwiązań w mniejszych, niezależnych partiach. Poza tym chcąc napisać dobry silnik 2D , należy przebudować sposób wyświetlania warstw. Jak ktoś z czytelników widział mój programik Gigant2D ( www.delphi.ilion.pl dział narzędzia ) to na pewno zwrócił uwagę, że FPS osiąga wartości rzędu 190- 260 i to nie zależnie od wielkości świata czy to 30×30 czy tez 2000×2000 klatek dla trzech warstw. Moje rozwiązanie użyte w Gigancie tak samo będzie działać w izometrycznym świecie…. Model w omawianych części przyjąłem najprostszy bo nie jest on głównym tematem tych sześciu części.

Mam nadzieję, że te 6 części przyczynią się do popularyzacji OMEGI jak i DELPHI….

Czas kończyć bo zaczynam już wywyższać DELPHI:-)

Pozdrawiam oksal

5.06.2006 Zbylitowska Góra

Autor: oksal

Załączniki