Nie jestem pewien, czy nadal to czytasz, ale od dłuższego czasu zmagam się z tego rodzaju problemami.
Zaprojektowałem wiele różnych rodzajów systemów afektu. Omówię je teraz krótko. Wszystko opiera się na moim doświadczeniu. Nie twierdzę, że znam wszystkie odpowiedzi.
Modyfikatory statyczne
Ten typ systemu opiera się głównie na prostych liczbach całkowitych w celu określenia jakichkolwiek modyfikacji. Na przykład +100 do Max HP, +10 do ataku i tak dalej. Ten system może również obsługiwać procenty. Musisz tylko upewnić się, że układanie nie wymknie się spod kontroli.
Tak naprawdę nigdy nie buforowałem wygenerowanych wartości dla tego typu systemu. Na przykład, jeśli chciałbym wyświetlić maksymalne zdrowie czegoś, wygenerowałbym wartość na miejscu. Zapobiegło to podatności na błędy i było łatwiejsze do zrozumienia dla wszystkich zaangażowanych.
(Pracuję w Javie, więc to, co następuje, jest oparte na Javie, ale powinno działać z pewnymi modyfikacjami dla innych języków). Ten system można łatwo wykonać za pomocą wyliczeń dla typów modyfikacji, a następnie liczb całkowitych. Wynik końcowy można umieścić w jakiejś kolekcji, która zawiera pary uporządkowane według klucza i wartości. Będzie to szybkie wyszukiwanie i obliczenia, więc wydajność jest bardzo dobra.
Ogólnie rzecz biorąc, działa bardzo dobrze z prostymi modyfikatorami statycznymi. Chociaż kod musi istnieć w odpowiednich miejscach, aby można było użyć modyfikatorów: getAttack, getMaxHP, getMeleeDamage i tak dalej.
Gdy ta metoda zawodzi (dla mnie), jest to bardzo złożona interakcja między wzmocnieniami. Nie ma naprawdę łatwego sposobu na interakcję, chyba że trochę ją poprawisz. Ma kilka prostych możliwości interakcji. W tym celu należy zmodyfikować sposób przechowywania modyfikatorów statycznych. Zamiast używać wyliczenia jako klucza, używasz ciągu znaków. Ten ciąg byłby nazwą Enum + dodatkowa zmienna. 9 razy na 10 dodatkowa zmienna nie jest używana, więc nadal zachowujesz nazwę wyliczenia jako klucz.
Zróbmy szybki przykład: jeśli chcesz mieć możliwość modyfikowania obrażeń zadawanych nieumarłym stworzeniom, możesz mieć taką uporządkowaną parę: (DAMAGE_Undead, 10) USZKODZENIE to Enum, a Nieumarli to dodatkowa zmienna. Podczas walki możesz zrobić coś takiego:
dam += attacker.getMod(Mod.DAMAGE + npc.getRaceFamily()); //in this case the race family would be undead
W każdym razie działa dość dobrze i jest szybki. Ale zawodzi przy złożonych interakcjach i wszędzie ma „specjalny” kod. Weźmy na przykład sytuację „25% szans na teleportację po śmierci”. Jest to „dość” złożony proces. Powyższy system może to obsłużyć, ale nie łatwo, ponieważ potrzebujesz następujących elementów:
- Sprawdź, czy gracz ma ten mod.
- Gdzieś, jeśli uda się uzyskać teleportację, przygotuj kod. Lokalizacja tego kodu jest dyskusją samą w sobie!
- Uzyskaj odpowiednie dane z mapy Mod. Co oznacza wartość? Czy to w pokoju też się teleportują? Co jeśli gracz ma na sobie dwa mody teleportacji? Czy kwoty się nie sumują ?????? NIEPOWODZENIE!
To prowadzi mnie do następnego:
The Ultimate Complex Buff System
Kiedyś sam próbowałem napisać 2D MMORPG. To był okropny błąd, ale wiele się nauczyłem!
Przepisałem system afektu 3 razy. W pierwszym zastosowano mniejszą odmianę powyższego. Drugi był tym, o czym zamierzam mówić.
Ten system miał szereg klas dla każdej modyfikacji, więc rzeczy takie jak: ChangeHP, ChangeMaxHP, ChangeHPByPercent, ChangeMaxByPercent. Miałem milion takich ludzi - nawet takie rzeczy jak TeleportOnDeath.
Moje zajęcia miały rzeczy, które mogłyby wykonać następujące czynności:
- ApplyAffect
- removeAffect
- checkForInteraction <--- ważne
Zastosuj i usuń wyjaśnienia same (chociaż w przypadku takich rzeczy, jak procenty, efekt będzie śledził, o ile zwiększył on HP, aby upewnić się, że kiedy efekt się skończy, usunie tylko dodaną kwotę. To był błąd, lol i zajęło mi dużo czasu, aby upewnić się, że wszystko jest w porządku. Nadal nie czułem się dobrze.).
Metoda checkForInteraction była przerażająco złożonym fragmentem kodu. W każdej klasie wpływów (tj .: ChangeHP) miałby kod określający, czy należy to zmodyfikować przez wpływ wejściowy. Na przykład, jeśli masz coś takiego ...
- Wzmocnienie 1: Zadaje 10 obrażeń od ognia podczas ataku
- Wzmocnienie 2: Zwiększa wszystkie obrażenia od ognia o 25%.
- Wzmocnienie 3: Zwiększa wszystkie obrażenia od ognia o 15.
Metoda checkForInteraction poradziłaby sobie z tymi wszystkimi skutkami. Aby to zrobić, każdy wpływ na WSZYSTKICH graczy w pobliżu musiał zostać sprawdzony !! Wynika to z tego, że rodzaj wpływów, z którymi miałem do czynienia w przypadku wielu graczy na danym obszarze. Oznacza to, że kod NIGDY NIE MIAŁ JAKICHKOLWIEK specjalnych stwierdzeń jak wyżej - „jeśli właśnie umarliśmy, powinniśmy sprawdzić teleportację po śmierci”. Ten system automatycznie obsłużyłby go poprawnie we właściwym czasie.
Próba napisania tego systemu zajęła mi około 2 miesięcy i kilka razy wybuchła głową. JEDNAK, był NAPRAWDĘ potężny i potrafił robić szaloną ilość rzeczy - szczególnie gdy weźmiesz pod uwagę następujące dwa fakty dotyczące umiejętności w mojej grze: 1. Miały zakresy docelowe (tj .: pojedyncze, własne, tylko grupowe, własne PB AE , Cel PB AE, docelowa AE itd.). 2. Zdolności mogą mieć na nie więcej niż 1 wpływ.
Jak wspomniałem powyżej, był to system wpływów 2 i 3 dla tej gry. Dlaczego się od tego odsunąłem?
Ten system miał najgorszą wydajność, jaką kiedykolwiek widziałem! To było strasznie wolne, ponieważ musiało tak dużo sprawdzać każdą rzecz, która się wydarzyła. Próbowałem to poprawić, ale uznałem to za porażkę.
Przechodzimy do mojej trzeciej wersji (i innego rodzaju systemu buffów):
Złożona klasa afektów z programami obsługi
Jest to więc prawie kombinacja dwóch pierwszych: możemy mieć zmienne statyczne w klasie Affect, która zawiera wiele funkcji i dodatkowe dane. Następnie po prostu wywołaj procedury obsługi (dla mnie, prawie niektóre statyczne metody narzędzi zamiast podklas dla określonych akcji. Ale jestem pewien, że możesz przejść z podklasami dla akcji, jeśli chcesz), kiedy chcemy coś zrobić.
Klasa afektu miałaby wszystkie soczyste dobre rzeczy, takie jak typy celów, czas trwania, liczba zastosowań, szansa na wykonanie itd.
Wciąż musielibyśmy dodać specjalne kody, aby poradzić sobie z sytuacjami, na przykład teleportować się po śmierci. Nadal będziemy musieli to sprawdzić ręcznie w kodzie walki, a jeśli tak, to dostaniemy listę wpływów. Ta lista afektów zawiera wszystkie aktualnie stosowane afekty na graczu, który zajmował się teleportacją po śmierci. Następnie spojrzeliśmy na każdy z nich i sprawdziliśmy, czy wykonał się on i był udany (zatrzymalibyśmy się przy pierwszym udanym). Udało się, po prostu zadzwoniliśmy do przewodnika, aby się tym zajął.
Jeśli chcesz, możesz również wykonać interakcję. Musiałby tylko napisać kod, aby wyszukać określone wzmocnienia w odtwarzaczach / etc. Ponieważ ma dobrą wydajność (patrz poniżej), powinno być dość wydajne. Potrzebowałby po prostu bardziej złożonych programów obsługi i tak dalej.
Ma więc dużą wydajność pierwszego systemu i wciąż dużo złożoności, jak drugi (ale nie tak bardzo). Przynajmniej w Javie możesz zrobić kilka trudnych rzeczy, aby uzyskać wydajność prawie pierwszej w większości przypadków (np. Mając mapę enum ( http://docs.oracle.com/javase/6/docs/api/java) /util/EnumMap.html ) z Enums jako kluczami i ArrayList afektów jako wartości. To pozwala zobaczyć, czy szybko masz afekty [ponieważ lista wynosiłaby 0 lub mapa nie miałaby enum] i nie posiadając do ciągłego iterowania list afektów bez powodu. Nie mam nic przeciwko iteracji nad afektami, jeśli ich potrzebujemy w tej chwili. Zoptymalizuję później, jeśli stanie się to problemem).
Obecnie ponownie otwieram (przepisuję grę w Javie zamiast bazy kodu FastROM, w której była pierwotnie), mój MUD, który zakończył się w 2005 roku, a ostatnio natknąłem się na to, jak chcę wdrożyć mój system buffów? Będę używać tego systemu, ponieważ działał dobrze w mojej poprzedniej nieudanej grze.
Cóż, mam nadzieję, że ktoś gdzieś znajdzie przydatne informacje.