Pracuję nad grą, w której od czasu do czasu muszą się zdarzyć niektóre wydarzenia w grze. Dobrym przykładem byłby samouczek. Rozpoczynasz grę, aw kilku momentach gry następuje zdarzenie:
- Spotkasz pierwszego wroga, gra się zatrzyma i otrzymasz wyjaśnienie, jak go zabić.
- Zabiłeś pierwszego wroga, otrzymasz wiadomość „dobrej roboty”.
- Zyskujesz nowy przedmiot, menu z wyskakującymi statystykami przedmiotów.
- itd itd.
Gra, nad którą pracuję, to łamigłówka, w której zasady są prawie takie same, więc wydaje się nieefektywne zakodowanie wszystkich tych zdarzeń na osobnych poziomach.
Czy powinienem jakoś zdefiniować te zdarzenia w zewnętrznym źródle, takim jak XML? Następnie napisać interpreter, który odczytuje XML i określa wymagania dotyczące zdarzeń na poziomie? Nie jestem pewien, jak mógłbym zdefiniować zdarzenie, które powinno nastąpić, gdy zabiłeś na przykład dwóch wrogów.
Żeby było jasne, nie szukam najlepszego języka programowania ani języka skryptowego do tego, ale więcej najlepszej metody radzenia sobie z tym.
Dzięki!
Edycja: Drugi przykład, ponieważ moje pytanie było dość trudne do zrozumienia:
Problem, który mam, polega na tym, by w grze wykonać kilka dodatkowych działań w taki sam sposób. Podobnie jak w bitwie RPG, każdy ma swoją kolej, wybiera umiejętność itp. - zawsze jest tak samo. Ale co, jeśli byłby przypadek, w którym chciałbym wyświetlić przerywnik gdzieś pomiędzy. Modyfikowanie całej struktury gry w zmienionej klasie bojowej z włączoną przerywnikiem wydaje się bardzo nieefektywne. Zastanawiam się, jak to się zwykle robi.
źródło
Odpowiedzi:
Zależy to w dużej mierze od tego, jak zdarzenia są faktycznie komunikowane między obiektami w grze. Na przykład, jeśli używasz centralnego systemu przesyłania wiadomości, możesz mieć moduł samouczka, który nasłuchuje określonych wiadomości i tworzy wyskakujące okienka samouczka, gdy tylko usłyszy niektóre wiadomości. Następnie możesz ustawić, jakiej wiadomości należy słuchać, wraz z wyskakującym okienkiem do wyświetlenia, w pliku XML lub innym obiekcie analizowanym przez moduł samouczka. Mając osobny obiekt samouczka, który monitoruje stan gry i wyświetla wyskakujące okienka samouczka, gdy zauważy rzeczy w grze, możesz dowolnie zmieniać obiekt samouczka bez potrzeby zmiany czegokolwiek w grze. (Czy to wzór Observer? Nie znam wszystkich wzorów).
Ogólnie rzecz biorąc, zależy to od złożoności twojego samouczka, czy warto się o to martwić. Twarde kodowanie zdarzeń w twoim kodzie i / lub poziomach nie wydaje mi się wielką przeszkodą dla zaledwie kilku podręcznych okien podręcznych. Jestem ciekawy, co dokładnie masz na myśli, co sprawia, że myślisz, że będzie to nieefektywne, ponieważ wszystko, co powinieneś robić przy każdym wyzwalaczu, to po prostu wysłanie wiadomości do modułu samouczka, coś takiego jak TutorialModule.show („1st_kill”);
źródło
Oto ograniczenia projektowe, jakie rozumiem:
Podstawowy kod rozgrywki nie dba o wymagania dotyczące poziomu i nie powinien być łączony z kodem, który je obsługuje.
Jednocześnie jest to podstawowy kod rozgrywki, który wie, kiedy wystąpią określone zdarzenia spełniające te wymagania (zdobycie przedmiotu, zabicie wroga itp.)
Różne poziomy mają różne zestawy wymagań, które należy gdzieś opisać.
Biorąc to pod uwagę, prawdopodobnie zrobiłbym coś takiego: Po pierwsze, stwórz klasę reprezentującą poziom gry. Będzie zawierał zbiór szczegółowych wymagań, jakie ma dany poziom. Ma metody, które można wywoływać w przypadku wystąpienia zdarzeń w grze.
Podaj podstawowy kod rozgrywki jako odniesienie do obiektu na bieżącym poziomie. W przypadku wystąpienia zdarzenia rozgrywki, powie to poziom poprzez wywołanie metody na niej:
enemyKilled
,itemPickedUp
, itd.Wewnętrznie
Level
potrzebuje kilku rzeczy:LevelRequirement
obiektów opisujących konkretny zestaw celów, których potrzebujesz na tym poziomie.Kiedy wejdziesz na poziom, stworzysz
Level
właściwy,LevelRequirement
s ustawi kod gry i nadasz mu ten poziom.Za każdym razem, gdy pojawia się zdarzenie w grze, rozgrywka przechodzi do niego
Level
. To z kolei oblicza dane zagregowane (całkowita liczba zabitych wrogów, zabitych wrogów tego typu itp.) Następnie przechodzi przez obiekty wymagań, podając każdemu dane zbiorcze. Wymaganie sprawdza, czy jest spełniony, a jeśli tak, odradza się odpowiednie zachowanie wynikowe (wyświetlanie tekstu samouczka itp.)LevelRequirement
w zasadzie potrzebuje dwóch rzeczy:RequirementType
Mam wyliczenie z takimi rzeczami,FIRST_KILL
a potem dużą rzecz,switch
która wie, jak sprawdzić każdy rodzaj.)Wciąż pozostaje pytanie, gdzie te zestawy wymagań są opisane. Możesz zrobić coś takiego jak XML lub inny format pliku tekstowego. Jest to przydatne, jeśli:
Jeśli tak nie jest, prawdopodobnie po prostu zbuduję je bezpośrednio w kodzie. Prostsze jest zawsze lepsze.
źródło
Pomyślałem, że musisz wiedzieć, jak tworzyć te zdarzenia, a reszta postu dotyczy tego. Jeśli chcesz po prostu przechowywać te zdarzenia, skorzystaj z relacyjnej bazy danych lub opisz je tekstem i użyj języka skryptowego (zrobi to parsowanie i ocenę Ty). :)
To, co chcesz, to rozpoznać zdarzenia, które się wydarzyły (1), a następnie wykonać pewne czynności wymagane przez te zdarzenia (wydrukuj wiadomość, sprawdź naciśnięcie klawisza ...) (2). Chcesz również, aby te zdarzenia zdarzały się tylko raz (3).
Zasadniczo chcesz sprawdzić warunki, a następnie zaplanować pewne zachowanie.
Jak rozpoznać zdarzenia (1)
Z czego wykonane są wydarzenia
Mówiąc bardziej ogólnie, każde takie zdarzenie składa się z:
Jak przechowywać te wydarzenia
W niektórych strukturach danych:
Możesz również przechowywać go w relacyjnej bazie danych, chociaż wygląda na to, że nie jest to konieczne, jeśli chcesz stworzyć tę grę w dużych rozmiarach, być może będziesz musiał ją stworzyć.
Następnie musisz przeanalizować te ciągi / rzeczy. Lub możesz użyć jakiegoś języka skryptowego, takiego jak Python lub LUA, lub języka takiego jak LISP, wszystkie one mogą przeanalizować i wykonać dla Ciebie. :)
Jak korzystać z tych zdarzeń w pętli gry (2)
Będziesz potrzebować tych dwóch struktur danych:
Algorytm:
Jak samodzielnie wykonać te działania (2)
Tworzysz listę obiektów, które mają funkcję „aktualizacja”. Czasami nazywane są bytami (w silniku Quake) lub aktorami (w silniku Unreal).
Akcja „powiedz coś”
Działanie „wymaga klucza”
Jakie metody się uczyć
źródło