Jakiej struktury danych należy użyć dla drzewa talentów w stylu Diablo / WoW?
23
Zastanawiam się nad wdrożeniem systemu drzewa talentów do internetowej gry RPG, podobnej do tej w World of Warcraft, gdzie zdobycie umiejętności odblokowuje kolejny „poziom” pod nią w drzewie.
Czy ktoś wie o najlepszym sposobie implementacji tego strukturalnie w bazie danych / kodzie?
Użyj takiej struktury, aby przedstawić drzewo w bazie danych:
#Talent
id parent description
10Tackle21Kick31Punch43FirePunch
I kolejna tabela reprezentująca nabyte talenty na użytkownika
#UserTalent
id user talent
141243344
Możesz programowo sprawdzić zależności między talentami, sprawdzając pełną tabelę talentów i budując połączone drzewo. Możesz to zrobić również za pomocą SQL, ale będzie to wymagało rekursywnych podselekcji lub wielu zapytań. Lepiej zrób to w kodzie.
Jeśli istnieje wiele zależności, na przykład Fire Punchzależy od PunchAND, Immolationużyj dwóch tabel do przedstawienia wykresu zależności:
#Talent
id description
1Tackle2Kick3Punch4FirePunch5Immolation#Depedency
id parent child
101205312413534654
Twój UserTalentstół nie potrzebuje kolumny z kluczem automatycznym. useri talentmogą być jedynymi dwiema kolumnami i kluczem złożonym: nigdy nie będą duplikatami, a ty i tak nigdy nie idzapytasz.
doppelgreener
Nie jestem projektantem baz danych i chciałbym usłyszeć czyjąś opinię na ten temat: jeśli każdy talent miałby unikalną nazwę, czy nie mógłbyś również pozbyć się każdego innego pola liczbowego w tym projekcie tabeli i używać nazw jako kluczy (z jakieś zmiany kaskadowe)? Czy byłoby to znaczące koszty lub korzyści?
doppelgreener
3
@Jathanathan Hobbs: Podstawowy identyfikator autoinkrementacji jest zawsze miły dla operacji usuwania / aktualizacji. Nigdy nie jest wolniejszy, ale często szybszy. Również rozmiar wiersza nie ma tu znaczenia. To samo dotyczy przypadku wyjątkowych nazwisk talentów. Aby uzyskać dobrą wydajność, chcesz dołączyć do swoich tabel tylko na unikatowych liczbach całkowitych. Zobacz en.wikipedia.org/wiki/Database_normalization itp.
Jonas Bötel
Dzięki. Projektant DB, którego znałem kiedyś, stwierdził, że autokeys są złe i należy ich unikać, ale nigdy nie byłem pewien, czy tak jest i dlaczego. Chyba nie jest.
doppelgreener
Nie ma żadnego rzeczywistego powodu, aby używać bazy danych do przechowywania tych danych, chyba że potrzebujesz bazy danych dla projektantów, ponieważ obsługujesz edycję dla wielu użytkowników lub coś takiego. W przeciwnym razie będzie to przeszkadzało. (Nigdy też nie użyłbym do tego podstawowego klucza
5
Polecam użycie drzewa, w którym każdy węzeł reprezentuje określony talent / umiejętność. W zależności od tego, czy gracz zdobył talent, można go zdobyć. Na przykład następująca struktura danych
Aby ustalić, jakie talenty ma gracz, weź główny talent i idź w dół wykresu, aż dojdziesz do węzłów talentów, w których zdobyta wartość jest fałszywa. Ujawni to również, które talenty są dostępne do zdobycia: pierwszy talent w każdej gałęzi w dół od głównego talentu, w którym zarobione są fałszywe.
Masz wskaźnik do natywnej tablicy i rozmiar? Niepowodzenie - użyj samozmieniającego się wskaźnika.
DeadMG
Ups ... Mieszanie C / C ++ i błąd. Zaktualizowałem swoją odpowiedź. Dzięki za zgłoszenie się.
duch
@DeadMG: co dokładnie masz na myśli, mówiąc o „samowystarczalnym samorozmiaru”? Czy masz na myśli coś takiego jak wektor powyżej, czy też myślałeś o czymś innym?
Kylotan
Zwiększenie ptr_vectormoże być jeszcze lepsze.
Zan Lynx
5
Struktura drzewa powinna być całkowicie oddzielona od tego, czy gracz ją zarobił, te pierwsze to statyczne dane tworzone przez projektantów, a drugie to dane dotyczące poszczególnych graczy przechowywane w zapisanej grze lub DB.
1
W mojej grze robię to tak:
Baza danych:
reference_talent : zawiera unikalny identyfikator, nazwę, efekt itp
talent : id, playerid <- zawiera wszystkie talenty, których „nauczyli się” gracze.
Ingame: (na serwerze)
Ładuję wszystkie pliki referencyjne na „statycznej” (tylko do odczytu) std :: map, dzięki czemu mogę łatwo uzyskać do nich dostęp dzięki ich identyfikatorowi.
Kiedy klient sprawdza gracza, pobieram wszystkie talenty z bazy danych i gromadzę je w standardzie std :: vector, aby kiedy potrzebowałem obliczyć cechy itp., Mam je w pamięci RAM. Wysyłam również talenty do klienta.
To wszystko (oprócz oszczędzania nowych talentów, które są po prostu „WSTAW” w tabeli „talent” + wiadomość dla klienta).
Opisujesz to jako relację między odblokowaniem a odblokowaniem podobnie jak w tym samouczku . Sugeruję, aby dowiedzieć się więcej na temat algebry relacyjnej i baz danych. Są dobrym sposobem modelowania danych. Jeśli nauczysz się wyszukiwać informacje z bazy danych, możesz dość łatwo modelować dane.
Nie wiem ile wiesz o modelowaniu relacji. Ten samouczek powinien ci w tym pomóc.
Jedno rozwiązanie
Zakładam, że WoW działa tak jak w rzeczywistości (ehm), że tak jest
talent odblokowuje kilka (innych) talentów
talent odblokowuje kilka (innych) talentów.
Jest to relacja N: N, co oznacza, że potrzebujesz „średniego człowieka” nowej relacji między dwoma talentami:
(talent who unlocks id, talent who is unlocked)
W ten sposób możesz odblokować talent A odblokowujący B, C i D ((A, B), (A, C), (A, D)) i talent Y odblokowany przez X, Z i W ((X, Y), ( Z, Y), (W, Y)). W języku imperatywnym / proceduralnym / obiektowym Zrobiłbyś to jako listę / tablicę par takich jak tam:
var unlocks_unlocked =[[A, B],[A,C],[A,D],[X,Y],[Z,Y],[W,Y]];
UserTalent
stół nie potrzebuje kolumny z kluczem automatycznym.user
italent
mogą być jedynymi dwiema kolumnami i kluczem złożonym: nigdy nie będą duplikatami, a ty i tak nigdy nieid
zapytasz.Polecam użycie drzewa, w którym każdy węzeł reprezentuje określony talent / umiejętność. W zależności od tego, czy gracz zdobył talent, można go zdobyć. Na przykład następująca struktura danych
Aby ustalić, jakie talenty ma gracz, weź główny talent i idź w dół wykresu, aż dojdziesz do węzłów talentów, w których zdobyta wartość jest fałszywa. Ujawni to również, które talenty są dostępne do zdobycia: pierwszy talent w każdej gałęzi w dół od głównego talentu, w którym zarobione są fałszywe.
źródło
ptr_vector
może być jeszcze lepsze.W mojej grze robię to tak:
Baza danych:
reference_talent : zawiera unikalny identyfikator, nazwę, efekt itp
talent : id, playerid <- zawiera wszystkie talenty, których „nauczyli się” gracze.
Ingame: (na serwerze)
Ładuję wszystkie pliki referencyjne na „statycznej” (tylko do odczytu) std :: map, dzięki czemu mogę łatwo uzyskać do nich dostęp dzięki ich identyfikatorowi.
Kiedy klient sprawdza gracza, pobieram wszystkie talenty z bazy danych i gromadzę je w standardzie std :: vector, aby kiedy potrzebowałem obliczyć cechy itp., Mam je w pamięci RAM. Wysyłam również talenty do klienta.
To wszystko (oprócz oszczędzania nowych talentów, które są po prostu „WSTAW” w tabeli „talent” + wiadomość dla klienta).
źródło
Podejście relacyjne
Opisujesz to jako relację między odblokowaniem a odblokowaniem podobnie jak w tym samouczku . Sugeruję, aby dowiedzieć się więcej na temat algebry relacyjnej i baz danych. Są dobrym sposobem modelowania danych. Jeśli nauczysz się wyszukiwać informacje z bazy danych, możesz dość łatwo modelować dane.
Nie wiem ile wiesz o modelowaniu relacji. Ten samouczek powinien ci w tym pomóc.
Jedno rozwiązanie
Zakładam, że WoW działa tak jak w rzeczywistości (ehm), że tak jest
Jest to relacja N: N, co oznacza, że potrzebujesz „średniego człowieka” nowej relacji między dwoma talentami:
W ten sposób możesz odblokować talent A odblokowujący B, C i D ((A, B), (A, C), (A, D)) i talent Y odblokowany przez X, Z i W ((X, Y), ( Z, Y), (W, Y)). W języku imperatywnym / proceduralnym / obiektowym Zrobiłbyś to jako listę / tablicę par takich jak tam:
Na przykład w „świecie rzeczywistym” możesz mieć:
i oznacza to, że „skok superhigh” uzyskuje się po tym, jak masz talent „szybkiego biegania” i „dziecka antygrawitacji”.
Inne rozwiązanie
Ostatnio nie grałem w Diablo, ale możliwe, że miał tylko:
Jest to relacja 1: N:
lubić:
źródło