Kodowanie nie jest trudne w rzeczywistości . Trudność polega na pisaniu kodu, który ma sens, jest czytelny i zrozumiały. Chcę więc uzyskać lepszego programistę i stworzyć solidną architekturę.
Więc chcę zrobić stworzyć architekturę NPC w grze wideo. Jest to gra strategiczna w czasie rzeczywistym, taka jak Starcraft, Age of Empires, Command & Conquers, itp. Itd. Więc będę mieć różnego rodzaju NPC. NPC może mieć jeden do wielu możliwości (metody) tych: Build()
, Farm()
i Attack()
.
Przykłady:
Pracownik może Build()
i Farm()
Wojownik może Attack()
Obywatel może Build()
, Farm()
a Attack()
rybak może Farm()
iAttack()
Mam nadzieję, że do tej pory wszystko jest jasne.
Teraz mam swoje typy NPC i ich umiejętności. Ale przejdźmy do aspektu technicznego / programowego.
Jaka byłaby dobra architektura programowa dla moich różnych postaci niezależnych?
Okej, mógłbym mieć klasę podstawową. Właściwie uważam, że jest to dobry sposób na przestrzeganie zasady OSUSZANIA . Mogę mieć metody jak WalkTo(x,y)
w mojej klasie podstawowej, ponieważ każdy NPC będzie mógł się poruszać. Ale teraz przejdźmy do prawdziwego problemu. Gdzie wdrażam swoje umiejętności? (pamiętaj: Build()
, Farm()
i Attack()
)
Ponieważ umiejętności będą się składały z tej samej logiki, irytująca / łamająca zasadę SUCHEGO zastosowania będzie wdrażana dla każdego NPC (Robotnika, Wojownika, ...).
Okej, mógłbym wdrożyć umiejętności w klasie podstawowej. Wymagałoby to pewnego rodzaju logiką, który sprawdza, czy NPC może używać zdolności X. IsBuilder
, CanBuild
.. Myślę, że to jest jasne, co chcę wyrazić.
Ale nie czuję się dobrze z tym pomysłem. To brzmi jak rozdęta klasa podstawowa o zbyt dużej funkcjonalności.
Używam C # jako języka programowania. Zatem wielokrotne dziedziczenie nie jest tutaj opcją. Oznacza: Posiadanie dodatkowych klas podstawowych takich jak Fisherman : Farmer, Attacker
nie będzie działać.
źródło
Odpowiedzi:
Skład i dziedziczenie interfejsu są zwykłymi alternatywami dla klasycznego dziedziczenia wielokrotnego.
Wszystko, co opisano powyżej, zaczynające się od słowa „może”, jest funkcją, którą można przedstawić za pomocą interfejsu, jak w
ICanBuild
lubICanFarm
. Możesz odziedziczyć tyle interfejsów, ile potrzebujesz.Możesz przekazywać „ogólne” obiekty budowlane i rolnicze przez konstruktora swojej klasy. Tam właśnie wchodzi kompozycja.
źródło
ICanBuild
. To, że masz również narzędzia do budowania, ma drugorzędne znaczenie w hierarchii obiektów.Jak wspomniano w innych plakatach, rozwiązaniem problemu może być architektura komponentów.
W takim przypadku rozszerz funkcję aktualizacji, aby zaimplementować dowolną funkcjonalność NPC.
Iteracja kontenera komponentu i aktualizacja każdego komponentu pozwala na zastosowanie określonej funkcjonalności każdego komponentu.
Ponieważ każdy typ obiektu jest pożądany, możesz użyć jakiejś formy wzorca fabrycznego, aby skonstruować poszczególne typy, które chcesz.
Zawsze miałem problemy, ponieważ komponenty stawały się coraz bardziej złożone. Utrzymanie niskiej złożoności komponentów (jedna odpowiedzialność) może pomóc w rozwiązaniu tego problemu.
źródło
Jeśli zdefiniujesz interfejsy w taki sposób,
ICanBuild
to twój system gry musi sprawdzać każdego NPC według typu, co zwykle jest niesmaczne w OOP. Na przykład:if (npc is ICanBuild)
.Lepiej jest z:
Następnie:
... lub oczywiście możesz użyć wielu różnych architektur, takich jak język specyficzny dla domeny w postaci płynnego interfejsu do definiowania różnych typów NPC itp., w których budujesz typy NPC poprzez łączenie różnych zachowań:
Konstruktor NPC może zaimplementować coś,
DefaultWalkBehavior
co może zostać zastąpione w przypadku NPC, który lata, ale nie może chodzić itp.źródło
if(npc is ICanBuild)
iif(npc.CanBuild)
. Nawet gdybym wolałnpc.CanBuild
drogę od mojego obecnego nastawienia.Umieściłbym wszystkie umiejętności w osobnych klasach, które dziedziczą po Umiejętności. Następnie w klasie typu jednostki masz listę umiejętności i innych rzeczy, takich jak atak, obrona, maksymalne zdrowie itp. Posiadasz również klasę jednostek, która ma bieżące zdrowie, lokalizację itp. I ma typ jednostki jako zmienną członka.
Zdefiniuj wszystkie typy jednostek w pliku konfiguracyjnym lub bazie danych, zamiast kodować na stałe.
Następnie projektant poziomów może łatwo dostosować umiejętności i statystyki typów jednostek bez ponownej kompilacji gry, a także ludzie mogą pisać mody do gry.
źródło