Forum jest aktualnie zamknięte.

Ocena wątku:
  • 1 głosów - średnia: 5
  • 1
  • 2
  • 3
  • 4
  • 5
Przemieszczanie się pomiędzy mapami
#1
Witam Was, szanowne gobliny!

Chciałem wam dzisiaj zaprezentować system swobodnego przechodzenia pomiędzy mapami (coś na wzór kampanii Rexxara). Zanim zaczniemy, słów kilka o samych wyzwalaczach i systemie.

Na wstępie chciałem napisać, że system, który wam przedstawię, został opracowany przeze mnie na zasadzie metod prób i błędów. Dlatego chciałbym ostrzec, iż możliwym jest występowanie tutaj pewnych błędów i niedociągnięć, które mogły mi umknąć, choć podczas testowania takowych nie zauważyłem. Jestem niemal pewien, że niektóre mechaniki i części wyzwalaczy można było wykonać lepiej pod względem optymalizacji i przejrzystości. W systemie nie są używane Tablice Mieszające.
Sama mechanika wykorzystywana do przechodzenia pomiędzy mapami jest stosunkowo prosta. Opiera się ona na wykorzystaniu Bufora Gry oraz tworzeniu i wczytywaniu zapisanych stanów map. W zasadzie główną trudnością tutaj jest poprawne opisanie zmiennych i zapisanie ich w buforze. Tworząc ten system starałem się uformować go, jako wyzwalacze uniwersalne, które będą łatwe do kopiowania pomiędzy mapami. W załączniku przesyłam Wam kampanię demonstracyjną, która posłuży nam również jako podstawa tego samouczka.
Ostatnią rzeczą, o której chciałbym wspomnieć jest to, że w czasie samouczka mogę do tego systemu zwracać się na zasadzie "mój system, w moim systemie, etc.". Systemów takich jak ten można znaleźć mnóstwo, nie jest to więc oryginalna i unikalna praca i w najmniejszym wypadku nie chcę sobie przypisać zasług za utworzenie czegoś, co już było. Używanie takich zwrotów jest dla mnie po prostu wygodniejsze. W samym samouczku ominąłem wyzwalacze dotyczące zadań i innych rzeczy nie związanych bezpośrednio z systemem przejścia. Zatem, do roboty!


1. Opracowanie planu kampanii oraz stworzenie zmiennych.
Stworzenie planu, na którym później będziemy się opierać, jest krokiem znacznie ułatwiającym naszą implementację systemu swobodnego przechodzenia (i nie tylko!).
Zakładamy, że nasza kampania będzie zawierała dwie mapy o nazwach przejscie01.w3x oraz przejscie02.w3m. Między mapami przenoszony będzie nasz bohater, jego punkty życia i many oraz nasze surowce. Dodatkowo przenoszone będą też zmienne dotyczące zadań, których wykonanie będzie wymagało przejścia z jednej mapy na drugą.
W prezentowanym systemie, z mapy pierwszej na drugą, można dostać się na dwa sposoby (istnieją dwie drogi). Pozwolę sobie zaprezentować swoje mistrzowskie umiejętności w programie Paint, aby zobrazować o co mi chodzi.

[Obrazek: przejscietutorialfox00.jpg]

Legenda:
Strefa przejściowa - miejsce, w którym nasze mapy będą się "łączyć".
Regiony wejściowe - wejście w ten region, spowoduje uruchomienie wyzwalaczy odpowiedzialnych za przeniesienie naszego bohatera do sąsiadującej mapy.
Regiony wyjściowe - w tych regionach nasz bohater się pojawi po wejściu w Region wejściowy na poprzedniej mapie.

Każde z przejść ma osobne oznaczenie numeryczne. Można to wykorzystać, jako indeks. Dlatego przejdziemy teraz do stworzenia zmiennych:

[Obrazek: przejscietutorialfox01.jpg]

Opis zmiennych:
jednostki_hero - do tej zmiennej przypisany będzie nasz bohater.
jednostki_hero_hp - punkty życia naszego bohatera.
jednostki_hero_mp - punkty many naszego bohatera.
przejscie_wymuszone_wczytanie - zmienna BDLBQ, która będzie odpowiadała za pewne zabezpieczenie. Wyjaśnię to później.
przybycie_indeks - indeks przejścia. Za jego pomocą, wchodząc w odpowiednie przejście na jednej mapie, pojawimy się w odpowiadającym mu miejscu na mapie drugiej.
punkt_tymczasowy - jak sama nazwa wskazuje.
region_przybycia - zmienna rozszerzona do tablicy. W tym regionie będziemy pojawiać się, po przybyciu na mapę.
surowce_drewno - nasze drewno.
surowce_zloto - nasze złoto.
zadania_szkielet_mag_bool - zmienna typu BDLBQ. Sprawdza ona, czy wykonaliśmy już pewną część zadania. Odpowiada ona za pojawienie się wroga na mapie przejscie01.w3x.
zadanie_szkielet_odkryte - zmienna typu BDLBQ. Sprawdza, czy zadanie Szkielet zostało odkryte na poprzedniej mapie. Służy do odkrycia zadania na mapie następnej.
zadanie_szkielet_wykonane - podobnie jak wyżej, z tym, że zmienna ta odpowiada za sprawdzenie, czy zadanie zostało wykonane na poprzedniej mapie.
zadanie_troll_killcount - zmienna typu C, licznik zabitych trolli.
Zmienne pokroju zadanie_troll_odkryte etc. mają tą samą rolę, co wymienione powyżej zmienne dotyczące zadania Szkielet. Reszta nie jest związana bezpośrednio z systemem przenoszenia.

Po stworzeniu zmiennych, możemy przejść do tworzenia wyzwalaczy.

2. Ustawienia początkowe, zapisanie zmiennych do bufora gry i zmiana mapy.

Na mapie pierwszej, tworzymy odpowiednie regiony, które posłużą nam do przenoszenia bohatera między mapami.

[Obrazek: przejscietutorialfox02.jpg]

Region zielony, to region przejscie do Polnoc 01 (region wejściowy). Wejście w ten region spowoduje uruchomienie wyzwalacza zapisującego mapę i przenoszącego nas na mapę drugą.
Region czerwony to region przybycie polnoc 01 (region wyjściowy). To tutaj nasz bohater pojawi się po przyjściu na tą mapę (jeśli skorzystał z odpowiedniego wejścia na tą mapę).
Podobną parę regionów tworzymy w innym miejscu na mapie.

Przechodzimy do wyzwalaczy:
2.1 Ustawienia początkowe

[Obrazek: przejscietutorialfox03.jpg]

W tym wyzwalaczu do zmiennej jednostki_hero przypisujemy bohatera, który będzie przenoszony między mapami. Natomiast do zmiennych region_przybycia[1] i region_przybycia[2] przypisujemy regiony wyjściowe czyli te, na których pojawi się nasz bohater. Indeksy tych regionów należy ustawić tak samo, jak oznaczyliśmy sobie Strefy Przejścia. Za pomocą tego indeksu wyzwalacze będą mogły określić gdzie wczytać naszego bohatera na następnej mapie.

Dalsze akcje odpowiadają za stworzenie zadań, które na mapie będziemy musieli wykonać.

2.2 Zapisanie danych do bufora gry
Następny wyzwalacz, jaki stworzymy, będzie się aktywował po wejściu w region wejściowy (np. przejscie do Polnoc 01). A wygląda on tak:

[Obrazek: przejscietutorialfox04.jpg]

Uwaga! - nie ma tego na załączonym obrazku, a być powinno, mianowicie na samym początku powinna znajdować się akcja Wyzwalacz - Turn off (This trigger). Dodatkowo powinien być warunek, mówiący o tym, że tylko nasz bohater uruchomi ten wyzwalacz.
Widoczna na zdjęciu akcja Set przejscie_wymuszone_wczytanie = TAK odpowiada za ustawienie zabezpieczenia przed uruchomieniem wyzwalacza, kiedy mapa będzie wczytywana "ręcznie". Więcej o tym napiszę przy wyzwalaczach wczytujących dane z bufora gry.

Ustalenie indeksu (Set przybycie_indeks = 1) służy do odpowiedniego usytuowania naszego bohatera na kolejnej mapie. Pojawi się on w regionie wyjściowym na mapie drugiej odpowiadającym regionowi wejściowemu na mapie pierwszej. Dzięki temu nasz bohater nie pojawi się w nielogicznych miejscach po przejściu na następną mapę.

Następnie należy przypisać życie i manę bohatera oraz surowce gracza do odpowiednich zmiennych. Potem inicjowany jest wyzwalacz zapisujący wszystkie dane na tej mapie:

[Obrazek: przejscietutorialfox05.jpg]

Zatrzymamy się tu na chwilę. Jeśli jesteś obeznany z tym, jak działają akcje Bufora Gry, to śmiało możesz przejść dalej.

Właściwe akcje zapisywania danych w buforze gry, zaczynają się od:
Bufor Gry - Create a game cache from TwojaNazwa.w3v .
Stworzymy zatem bufor o nazwie TwojaNazwa. Zalecam, aby nazwa nie zawierała polskich znaków i aby nie była zbyt długa. Postarajmy się też o jakąś unikalną, odpowiednią dla naszej kampanii nazwę, aby w przyszłości nie doszło do komplikacji w postaci operowania na takiej samej nazwie bufora w różnych kampaniach (prawdopodobieństwo jest małe, ale zawsze można je jeszcze zmniejszyć).
Jeśli podczas tworzenia kampanii planujesz operować na więcej, niż jednym buforze pamięci, to przypisz go do zmiennej (Zmienna typu Bufor Gry)! W naszym przypadku, w obu mapach będziemy operować tylko na jednym buforze. Dlatego w następnych akcjach mamy odniesienie do Last created game cache.

W buforze możemy przechowywać następujące typy zmiennych:
-jednostka (unit)
-liczba rzeczywista (real)
-liczba całkowita (integer)
-zmienna dwustanowa ( TAK/NIE - BDLBQ, Boolean)
-ciąg tekstowy (string)

Jeśli postanowimy zachować jakąś zmienną (np. jednostkę) w buforze gry, to będzie to miało następującą postać:

Bufor gry - Store Unit as Label of Category in (Last created game cache), gdzie:
Unit - zmienna przypisana do jednostki
Label - etykieta wykorzystywana w buforze gry do lokalizowania wpisu i wartości. Wpisywana ręcznie. Musi być unikalna dla różnych zmiennych.
Category - kategoria, w której zapisywane są etykietki (Label) przechowywanych zmiennych. W jednej kategorii może być wiele etykietek.

W efekcie, jeśli będziemy chcieli zapisać naszego bohatera w pamięci podręcznej, to nasza akcja przyjmie postać:

Bufor gry - Store jednostki_hero as hero of units in (Last created game cache), gdzie:
jednostki_hero - zmienna przypisana do naszego bohatera
hero - etykietka, którą wybrałem dla tej jednostki
units - kategoria w buforze gry, gdzie zapisywane będą moje jednostki.

Nazwy etykietek i kategorii powinny być w miarę intuicyjne, gdyż skomplikowane nazwy mogą nastręczać nam pewnych problemów w przyszłości (więcej w punkcie wczytywania danych).

Zatem, jak widać na załączonym wyżej obrazku, po akcji stworzenia buforu gry, zapisujemy w nim wszystkie nasze zmienne wedle powyższego schematu.

Na samym końcu dajemy akcję: Bufor gry - Save (Last created game cache), a następnie usuwamy naszego bohatera z mapy i inicjujemy wyzwalacz zmiany mapy.
Dodatkowo nie widać tego na obrazku, ale tutaj, przed akcją Wyzwalacz - Run Zmiana mapy (ignoring conditions)
powinny znajdować się akcje włączające wyzwalacze Wejscie w region przenoszenia polnoc01 oraz Wejscie w region przenoszenia polnoc02.

2.3 Zmiana mapy

Zmiana mapy jest przeprowadzona na dwa sposoby:
1) Zapisujemy obecną mapę i zmieniamy ją na inną.
2) Zapisujemy obecną mapę i wczytujemy zapis innej mapy.

Różnicą jest to, czy na mapie, na którą planujemy wejść, nasz bohater był już wcześniej. Jeśli nie, stosujemy punkt 1). Jeśli bohater był już na drugiej mapie i wrócił z niej, to wczytujemy punkt 2) .

Można to zrealizować poprzez wyzwalacz:

[Obrazek: przejscietutorialfox06.jpg]

Najpierw warunkiem sprawdzamy, jaki indeks został ustawiony. Jeśli numer indeksu wynosi 1 lub 2, to przenosimy naszego bohatera na mapę przejscie02.w3m .

Teraz stosujemy warunek sprawdzający, czy istnieje już zapisany stan mapy, na którą chcemy się przenieść. Jeśli tak, to zamiast zmieniać mapę na drugą (odpalenie mapy drugiej od początku), wczytujemy jej stan zapisu.

W przypadku punktu 1) (wchodzimy na mapę pierwszy raz) akcja wygląda tak:
Gra - Save game as mapa01.w3z and change level to przejscie02.w3m (Pomiń scores), gdzie:
-mapa01.w3z to zapisany stan mapy przejscie01.w3x
-przejscie02.w3m to nazwa mapy, do której się przenosimy.

Pamiętaj aby nazwy map były dokładne, wraz z zachowaniem ich rozszerzeń (w3x, w3m). Zauważyłem też, że długie nazwy map (zdaje się, że powyżej 40-45 znaków, wraz z rozszerzeniem) powodują problemy. Staraj się więc nazwy mieć jak najkrótsze.

W przypadku punktu 2) (wchodzimy na mapę ponownie)
Gra - Save game as mapa01.w3z and load mapa02.w3z (Pomiń scores), gdzie:
-mapa01.w3z to zapisany stan gry mapy przejscie01.w3x
-mapa02.w3z to zapisany stan gry mapy przejscie02.w3m

Po uruchomieniu tego wyzwalacza mapa zostanie zmieniona. W ten oto sposób przechodzimy do kolejnego i ostatniego już punktu.

3. Wczytywanie danych z bufora

Na mapie przejscie02.w3m, do której przechodzimy, tworzymy odpowiednie wyzwalacze:

[Obrazek: przejscietutorialfox07.jpg]

Czyli ponownie przypisujemy regiony do zmiennych i odpowiadające im indeksy (indeksy dobieramy tak, aby regiony wyjściowe na tej mapie, pasowały do regionów wejściowych na mapie poprzedniej).
Zwróć uwagę, że wyzwalacz ten zostanie uruchomiony tylko raz, tak samo jak wyzwalacz o nazwie Wczytywanie danych po raz pierwszy. Dzięki temu możemy zarówno wczytać dane z poprzedniej mapy, jak i ustawić coś na starcie mapy obecnej (np. stworzenie zadań, odpalenie intra), nie martwiąc się, że wyzwalacz ten będzie powtarzany za każdym razem, jak wejdziemy na tą mapę. Kolejnymi wczytaniami zajmie się już inny wyzwalacz o nazwie Wczytywanie danych ponownie.

Wczytywanie danych po raz pierwszy
[Obrazek: przejscietutorialfox08.jpg]

Następnie przystępujemy do wczytania danych z bufora. Kolejność akcji jakie wykonujemy przy wczytywaniu:
Bufor gry - Reload all game cache data from disk
czyli wczytanie wszystkich danych z dysku
Bufor gry - Create a game cache from TwojaNazwa.w3v
czyli na nowej mapie tworzymy bufor o dokładnie tej samej nazwie co bufor w mapie poprzedniej. Jeśli nazwa będzie się różnić, będziemy operowali na nowym buforze, który nie zawiera w sobie danych z poprzedniej mapy.

Dalej wczytujemy już dane z bufora i przypisujemy je do odpowiednich zmiennych, np:
Set przybycie_indeks = (Load indeks of przejscie from (Last created game cache)), gdzie:
-indeks - etykietka przypisana do zmiennej mającej wartość indeksu.
-przejscie - nazwa kategorii w której została zapisana powyższa etykietka.

Nazwy etykietek i kategorii muszą być identyczne, jak te w wyzwalaczach zapisujących dane do bufora. Inaczej nie uda nam się ich wczytać.

Wczytujemy bohatera na tą mapę, korzystając z akcji Bufor gry - Restore unit. Należy pamiętać, aby po tej akcji przypisać tą jednostkę do zmiennej jednostki_hero.

Następnie wczytujemy dane takie jak surowce, życie i mana bohatera, oraz stan zadań:

Rozwinięcie struktur If z poprzedniego obrazka.
[Obrazek: przejscietutorialfox09.jpg]

Widzimy tutaj dwie pary warunków:
Jeśli (Pierwsza para):
-Jeśli zadanie nie zostało ukończone na TEJ mapie
-Jeśli zadanie zostało odkryte na mapie poprzedniej
To Oznacz zadanie jako Odkryte.

Jeśli (Druga para warunków):
-Jeśli zadanie nie zostało ukończone na TEJ mapie
-Jeśli zadanie zostało ukończone na poprzedniej mapie
To Oznacz zadanie jako Ukończone.

Rozbudowanie tych struktur rośnie wraz z złożonością zadania do wykonania.

Następnie zapisujemy bufor gry i wyzwalamy gracza.

Różnica pomiędzy wyzwalaczami Wczytywanie danych po raz pierwszy oraz Wczytywanie danych ponownie są niewielkie.

Ten pierwszy wyzwalacz jest uruchamiany tylko raz i może w sobie zawierać akcje dotyczące początkowych ustawień mapy (np. odpalenie Intra etc.). Wyzwalacz ten nie posiada pewnego warunku, który obecny jest w wyzwalaczu Wczytywanie danych ponownie. Mianowicie chodzi o warunek sprawdzający o treści:

przejscie_wymuszone_wczytanie Równa się TAK

Ten jeden prosty warunek sprawdzający, czy wczytanie jest "wymuszone" przez wyzwalacze, czy też nie, uchroni nas przed uruchomieniem tych wyzwalaczy podczas operacji wczytania gry przez gracza.
Przykład:
Jesteśmy na mapie przejscie02.w3m . W wyzwalaczach wczytujących dane zabrakło warunku przejscie_wymuszone_wczytanie Równa się TAK.
W pewnym momencie podczas gry mama woła nas na obiad. Nie lubimy robić długich pauz w grach, więc zapisujemy grę i wyłączamy ją. Po niewątpliwie pysznym obiadku wracamy do komputera. Stwierdzamy, że chcemy dalej zagrać, więc odpalamy Warcrafta i wczytujemy naszą grę (poprzez Wczytaj grę). Mapka się uruchamia i co widzimy? Bohaterów na mapie jest dwóch, a nasze złoto i surowce wróciły do stanu z poprzedniej mapy oraz inne koszmarności.
Dzięki temu jednemu warunkowi możemy uchronić się przed taką sytuacją.

Jak wygląda wyzwalacz Wczytywanie danych ponownie:
[Obrazek: przejscietutorialfox10.jpg]

Jak widać, różnice są niewielkie.

Nota od autora - w zasadzie, można by pominąć tworzenie wyzwalacza Wczytywanie danych po raz pierwszy. Wszystkie dane dotyczące ustawień początkowych, intra itd. można by zawrzeć w wyzwalaczu który zaczynał by się od wydarzenia Map Initialization (co zapewni, że wyzwalacz uruchomi się tylko raz), a dane z bufora wczytać za pomocą akcji Wyzwalacz - Run Wczytywanie danych ponownie (ignoring conditions). No ale na razie zostawmy tak, jak jest.

4. Finito

Wyzwalacze w obu mapach wyglądają niemal identycznie. Istnieją w nich drobne różnice związane z wczytywaniem dodatkowych danych, które tyczą się tylko tej konkretnej mapy. System według mnie, jest łatwy do zaimplementowania, nawet jeśli map do których możemy swobodnie wchodzić jest znacznie więcej.
Problemy mogą pojawić się w przypadku dużej ilości zmiennych, które chcemy przenosić. Dotyczą one głównie nazywania Etykiet i Kategorii, a następnie poprawnego odnoszenia się do nich. Często bywa, że jedna literówka powoduje błędy z wczytywaniem jakiejś zmiennej z buforu. Należy więc zwracać na to szczególną uwagę. To samo tyczy się nazw zapisanych stanów gry i map oraz nazwy bufora gry.


UWAGA system ten posiada jedną zasadniczą wadę. Mianowicie, w momencie przechodzenia do kolejnej mapy, system sprawdza, czy nie istnieje już zapis (np. mapa02.w3z) sugerujący, że daną mapę już odwiedziliśmy.
Może zaistnieć sytuacja, w której dany stan zapisu będzie obecny, pomimo iż w danej kampanii ani razu nie byliśmy na tej mapie. Jak to możliwe?

1. Odpalamy kampanię. Przechodzimy ją i wyłączamy grę. Następnie stwierdzamy, że chcemy przejść daną kampanię jeszcze raz. No i tutaj pojawia się problem gdyż tzw. CustomSave'y już istnieją i kampania nam się wywali w momencie próby przejścia do innej mapy.

2. Podczas przechodzenia kampanii, będąc na mapie X, zapisujemy grę "ręcznie" przed wejściem na mapę Y. Będąc na mapie Y postanawiamy wrócić na mapę X (w momencie opuszczania mapy Y tworzy się już CustomSave).
Po chwili stwierdzamy, że wczytamy zapisaną PRZEZ NAS grę na mapie X (przed wejściem na mapę Y). Po wczytaniu gry, będziemy chcieli wejść na mapę Y i napotkamy błąd, gdyż zamiast wejść do niej po raz pierwszy, gra spróbuje wczytać jej CustomSave (gdyż będzie już obecny).

Obecnie staram się rozwiązać jakoś ten problem, jeśli uda mi się na coś wpaść to samouczek zostanie zaktualizowany ;)
Chętnie również przyjmę wszelkie sugestie.

Jedyna metoda, aby obecnie odpalić kampanię jeszcze raz, to wejść w folder z grą a następnie -> save/ProfileX/CustomSaves i skasować folder SystemPrzejscia.



No cóż, zdaje się, że to by było na tyle. Mam nadzieję, że system ten okaże się pomocny.

Pozdrawiam
FoX


Załączone pliki
.rar   SystemPrzejscia.rar (Rozmiar: 83.58 KB / Pobrań: 57)
ALWAYS ANGRY, ALL THE TIME!!
Odpowiedz
#2
Znalazłem jeden błąd. Otóż kiedy będziemy wracać do naszej mapy, to jednostki będą zresetowane. Proponuję dodać zmienną grupy jednostek (Wydaje mi się, że razem z jednostkami zapiszą się również ich punkty).
Ogólnie bardzo dobry poradnik. +Rep!
Odpowiedz
#3
Bezifabr, a co dokładniej masz na myśli mówiąc, że się zresetowały?
W sensie, że zostały zabite, a po powrocie na mapę odżyły?
ALWAYS ANGRY, ALL THE TIME!!
Odpowiedz
#4
chodzi o ożywienie, powrót na domyślną pozycję, ew. zresetowały hp.
Korzystając z grupy jednostek możesz każdą jednostkę przenieść pojedynczo na swoje pozycje.
Jest jeszcze kwestia martwych jednostek.. Można zrobić, że wszystkie jednostki tworzone są wyzwalaczami i jak nie ma jednostki w grupie po powrocie, to nie pojawi się ona na mapie.
Odpowiedz
#5
Możliwe, że wciąż nie do końca się rozumiemy. ;)
W mojej przykładowej kampanii, w myśl słynnego zdania "A kto umarł, ten nie żyje", jednostki, które zostały zabite na mapie, pozostaną już martwe, nawet jeśli wyjdziemy i ponownie wrócimy na tą mapę.

Ich aktualne położenie i np. poziom życia zostanie zapisany dokładnie w momencie, kiedy wyzwalacz zacznie zmieniać mapę (Save game as mapa01.w3z etc. etc. ). W efekcie, kiedy będziemy wracać na mapę zastaniemy ją w takim stanie, w jakim ją zostawiliśmy. Czyli jednostki martwe powinny być martwe, uszkodzone powinny być uszkodzone, a te żywe powinny być całkiem żywe :)

Taka dodatkowa adnotacja: Może to prowadzić do sytuacji, gdzie wychodząc z mapy, zapiszemy położenie jakiejś wrogiej jednostki (która nas ścigała) akurat przy przejściu. Należy zatem jednostki umieszczać dalej od regionów tranzytowych. :)
ALWAYS ANGRY, ALL THE TIME!!
Odpowiedz
#6
Przyda mi się, mało wyzwalaczy, działa na nowym patchu, szkoda tylko że zmienne po polsku, ale to sobie zmienię akurat.
Odpowiedz
  


Skocz do:


Użytkownicy przeglądający ten wątek:
1 gości