Maniacs Patch nie gryzie #7 – Rysowanie mapy podczas gry

Maniacs Patch posiada wiele opcji, które z uwagi na swoją świeżość nie zostały jeszcze szerzej wykorzystane na polskiej scenie. Sam dopiero zapoznaję się z tymi możliwościami i jestem oczarowany, w jaki kombajn zmienia RPG Makera 2003 BingShan. Chcę dołożyć swoją cegiełkę do popularyzowania tej modyfikacji, dlatego dziś pokażę, jak możemy rysować mapy podczas grania, a nie z poziomu edytora.

Przygotowania

Skrypt będzie maksymalnie uproszczony i będzie pokazywał jedynie ideę, którą należy twórczo rozwinąć, by nadawała się do normalnego projektu. Założenie jest takie:

  • gracz może wybierać spośród pięciu różnych kafelków;
  • postać gracza pełni rolę kursora;
  • mapę możemy dowolnie przerysowywać;
  • po wczytaniu gry program odtwarza narysowaną wcześniej mapę.

Istotny jest zwłaszcza ten ostatni punkt, ponieważ standardowo po zamknięciu i wczytaniu gry lub nawet teleporcie do innej lokacji, wszystkie zmiany na mapie dokonane za pomocą komend znikają.

Do skryptu użyję chipsetu Deathwinga, z którego wyciąłem pięć kafelków i przerobiłem je na charsety:

Spójrzmy na mapę

Będziemy pracować na minimalnym, mieszczącym się w oknie rozmiarze mapy – 20×15 kafelków. Maniacs umożliwia stworzenie mniejszej mapy, ale to już temat na zupełnie inny tekst. W edytorze nasza mapa wygląda tak:

Jeśli się nad tym chwilę zastanowić, jest to po prostu tabelka z rzędami i kolumnami. Licząc od lewej i od góry, można je ponumerować w następujący sposób:

Łącznie nasza mapa liczy więc 300 pól. Na każdym z nim może znajdować się tile z dolnej warstwy, element z górnej warstwy i zdarzenie. W tym tutorialu zajmujemy się tylko dolną warstwą.

Ustawiamy kursor

Jak wspomniałem, rolę kursora będzie pełnił gracz, którego charset będzie tożsamy z wybranym kafelkiem. Dlatego w pierwszej kolejności ustawiamy grafikę gracza w bazie danych na trawę, a następnie przechodzimy do common eventów. Tutaj tworzymy jeden odpowiedzialny za akcje gracza i przy pomocy komendy Key Input Processing przechwytujemy trzy klawisze – ENTER, ESC i SHIFT.

W pierwszej kolejności zajmiemy się ustawianiem kursora. Tutaj musimy zacząć od komendy Rewrite Map, która znajduje się na czwartej stronie komend zdarzeń. Po jej wciśnięciu pokaże się nam takie okienko:

Za chwilę omówimy je sobie dokładniej, ale teraz interesuje nas tylko boczny panel z elementami chipsetu. Jak widzicie, każdy kafelek, który możemy użyć z poziomu edytora, ma swój własny numer. Jeśli porównamy numer kafelków z wybranymi przeze mnie elementami do charsetu okaże się, że są następujące:

  • trawa – 6;
  • woda – 0;
  • gęsta trawa – 7;
  • ścieżka – 8;
  • kamienne płyty – 72.

Żeby to wykorzystać wracamy na mapę, którą będziemy modyfikować i ustawiamy event na autorun. Nową zmienną (to bardzo ważne – z numerem powyżej 300!) ustawiamy na 6 i usuwamy całe zdarzenie. Dzięki temu zawsze będziemy zaczynać grę z numerem kursora odpowiadającym za trawę. Należy także za pomocą komendy Set Move Route ustawić dla gracza Through ON. Dzięki temu kursor nie będzie blokowany przez kafle, po których normalnie nie można chodzić.

Teraz wracamy do naszego common eventa. Założenie jest takie, że po wciśnięciu klawisza SHIFT kursor zmienia się na kolejny z pięciu kafelków. Dlatego wystarczy stworzyć odpowiednie warunki sprawdzające jaki jest obecnie numer kursora i przypisujące mu kolejny z powyższej listy. Po zmianie odpowiedniej zmiennej pamiętajmy też o nowym wyglądzie bohatera!

Rysujemy mapę

Gdy mamy już przygotowany kursor, możemy przejść do nanoszenia naszych zmian na mapę. W tym celu przechodzimy do części common event odpowiedzialnego za wciśnięcie klawisza ENTER i do dwóch nowych zmiennych przenosimy współrzędne X oraz Y bohatera. Następnie ponownie odpalamy komendę Rewrite Map.

Po lewej stronie znajdują się następujące opcje:

  • Layer – wybieramy, czy chcemy zmeniać dolną, czy górną warstwę chipsetu;
  • Tile Type – wybieramy, jaki kafelek (lub zbiór kafelków) chcemy nanieść na mapę;
  • Position – ustawiamy w którym miejscu chcemy nanieść wybrany kafelek (X i Y to współrzędne na mapie, a W i H to szerokość i wysokość bloku, jeśli chcemy jednocześnie narysować więcej niż jeden kafelek);
  • Option – możemy wyłączyć autotile.

Nasza komenda powinna wyglądać następująco:

  • Layer – zostawiamy na dolnej warstwie;
  • Tile Type – tutaj ustawiamy zmienną z numerem kursora (po to wcześniej sprawdzaliśmy numery);
  • Position – tutaj wybieramy zmienne z X i Y bohatera, a W i H ustawiamy na 1;
  • Option – nie korzystamy z tej opcji, bo chcemy działające autotile.

Część dotyczącą rysowania mamy już gotową! Jeśli teraz wprowadzicie jakieś zmiany na mapie i następnie zapiszecie grę, po jej wczytaniu wszystko wróci do stanu pierwotnego. Na szczęście można temu zaradzić (podziękowania dla Axera za podsunięcie rozwiązania).

Baza danych z numerami kafli

Pamiętacie jak mówiłem, by nie wybierać zmiennych o numerach do 300 włącznie? To dlatego, że te zmienne będą stanowiły naszą bazę danych, gdzie będziemy zapisywać wygląd mapy. Na początek wracamy do eventa znajdującego się na mapie i dodajemy komendę, która wszystkim zmiennym o numerach od 1 do 300 ustawi numer 6 – czyli wskaże, że na tych kaflach znajduje się trawa.

To była ta prosta część. Teraz musimy zastanowić się, jak wpisywać do naszej bazy danych zmiany, które wykonaliśmy kursorem. W common evencie, w miejscu gdzie wciskamy ENTER, po komendzie Rewrite Map wywołujemy nowy common event o nazwie Wpis do bazy danych. To, co tam umieścimy mogłoby też znajdować się w pierwszy globalnym zdarzeniu, ale podczas prac nad takimi skryptami musimy też dbać o dobrą organizację pracy.

Musimy teraz zastanowić się, jak przy pomocy posiadanych informacji (współrzędne bohatera i numer kursora) ustalić, do której zmiennej odnosi się dany kafelek. Pamiętajcie, co może być nieco mylące, że program nie zaczyna liczyć kratek od 1, ale od 0. Jeśli przyjrzycie się tej tabeli zobaczycie, że znając współrzędną Y bohatera możemy ustalić, w którym rzędzie znajduje się interesująca nas liczba. Analogicznie postępujemy ze współrzędną X i kolumnami. Ustalenie odpowiedniej zmiennej to zaledwie kilka linijek kodu:

Do nowej zmiennej przypisujemy wartość współrzędnej Y bohatera. Jeśli pomnożymy ją przez 20 i dodamy 1, otrzymamy numer z pierwszej kolumny w tabeli. Następnie dodajemy wartość X i mamy numer zmiennej odpowiadającej za kratkę, na jakiej znajduje się bohater!

Teraz wystarczy tylko do zmiennej o ustalonym numerze przypisać wartość kursora.

Gdy teraz zapiszemy grę i ją wczytamy, nasze zmiany wciąż będą znajdować się w bazie. Problem w tym, że nadal nie będzie ich na mapie! To dlatego, że wartość bazy danych trzeba jeszcze przenieść na mapę.

Rysowanie mapy

Żeby wartość bazy danych znalazła się na mapie, trzeba ponownie użyć opcji rewrite. Tworzymy nowy common event o nazwie Rysowanie mapy.

Trigger zostawiamy na None, bo będzie on tylko wywoływany ręcznie. Możemy oczywiście sprawdzać po kolei 300 pól i je nanosić na mapę, ale to droga przez mękę. Potrzebujemy sposobu, by zautomatyzować cały proces, dlatego posłużmy się wskaźnikami i prostą pętlą. Całość wygląda tak:

Tworzymy trzy nowe zmienne – X Pola, Y Pola oraz ID zmiennej. Dwie pierwsze ustawiamy na 0, a trzecią na 1. Następnie wybieramy komendę Loop i w polu X Times ustawiamy 300 – tyle bowiem jest kafelków na mapie.

Pierwsza komenda wewnątrz pętli to Rewrite Map, gdzie miejsce rysowania kafelków wskazują zmienne X Pola i Y Pola, a numer kafelka znajduje się w zmiennej, której ID przechowuje przygotowana przed chwilą zmienna. Komenda powinna wyglądać tak:

Następnie zwiększamy wartość ID zmiennej o 1 (czyli będziemy rysować kolejny kafelek z bazy). W dalszej kolejności wstawiamy warunek sprawdzający, czy X Pola równa się 19. W opcji ELSE do tego warunku zwiększamy X Pola o 1. Natomiast wewnątrz warunku X Pola ustawiamy na 0, a Y Pola zwiększamy o 1. Dzięki takiemu zabiegowi jeśli rysowanie kratek dojdzie do końca wiersza, cofnie się na początek, ale wiersz niżej.

Gotowe! Zamiast łopatologicznego wklepywania 1000 linijek kodu, mamy 10 zgrabnych komend, które robią dokładnie tę samą robotę.

Pozostaje nam już tylko narysowanie zachowanej mapy po wczytaniu gry.

Rysowanie mapy po wczytaniu zapisu gry

Tutaj z pomocą przychodzi nam kolejne rozwinięcie Maniacs Patcha. Na mapie tworzymy zdarzenie z Triggerem na Parallel Process. Następnie tworzymy warunek, w którym na drugiej stronie wybieramy opcję Other2, a z niej – Right after load. Wewnątrz warunku wywołujemy common event Rysowanie mapy. To takie proste!

Jeśli teraz otworzycie projekt okaże się, że wszędzie jest woda. To dlatego, że warunek „Right after load” dotyczy nie tylko wczytywania zapisu, ale także zaczynania gry od nowa. Nasz skrypt rysuje wodę, ponieważ jeszcze nie zdążyliśmy do zmiennych przypisać wartości trawy z innego zdarzenia. Możemy to łatwo naprawić uzupełniając o wywołanie common eventa pierwsze zdarzenie, w którym przypisywaliśmy wartości do zmiennych. Dla uniknięcia problemów zmieniamy także komendę Erase Event na zmianę przełącznika i tworzymy nową, pustą stronę.

Podsumowanie

Tak naprawdę to już wszystko. Choć ten poradnik był dość długi, logika stojąca za przedstawionymi rozwiązaniami jest stosunkowo prosta i po przetrawieniu całkiem intuicyjna. Zastosowaną mechanikę można wykorzystać nie tylko we wszelkiej maści symulatorach, ale także przy tworzeniu innych gier, w których gracz może wpływać na swoje otoczenie. Jak się okazało, klawisz ESC do niczego nie był nam potrzebny. Dlatego możemy usunąć go z naszego pierwszego common eventa.

Michał „Michu” Wysocki

– Download przykładowego projektu –

Jeden komentarz do “Maniacs Patch nie gryzie #7 – Rysowanie mapy podczas gry

  1. Propozycja do Maniacs Patcha. To może naprawić w prosty sposób lub zmodyfikować łatwo wiele gier.
    Komenda, która wywołana na danej mapie – pozwoli zamienić na wszystkich pozostałych mapach zdarzenie o nazwie „,,,” (wpisujesz własną) na to zdarzenie na danej mapie, na której to zdarzenie jest wywołane. Pozwoli np: sprawić, że jeden typ zdarzenia przeciwnik z bugiem może zostać wyeliminowany lub zamieniony na poprawiony na wszystkich pozostałych mapach na ten jeden wzorcowy.

    Przykładowo zdarzenie z nazwą 0001 zamieniamy na „enemy1” i wywołujemy ten skrypt. Na wszystkich innych jeśli pojawia się zdarzenie „enemy1” zamieniamy te zdarzenia na zupdateowane na te z mapy z której obecnie wywołane zdarzenie podmiany.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.