Diablo / WoW tarzı yetenek ağacı için hangi veri yapısını kullanmalıyım?


23

Çevrimiçi bir RPG için yetenek ağacı sistemi kullanmayı düşünüyorum, World of Warcraft'ta görüldüğü gibi, bir beceri edinmenin ağacın altındaki bir sonraki “kademe” yi açıyor.

Bunu yapısal olarak veritabanında / kodunda uygulamanın en iyi yolunu bilen var mı?

Yanıtlar:


13

Veritabanındaki bir ağacı temsil etmek için böyle bir yapı kullanın:

#Talent
id  parent  description
1   0       Tackle
2   1       Kick
3   1       Punch
4   3       Fire Punch

Ve kullanıcı başına kazanılmış yetenekleri temsil eden başka bir tablo

#UserTalent
id  user  talent
1   4     1
2   4     3
3   4     4

Yetenek bağımlılıklarını programlı olarak tüm yetenek tablosunu sorgulayarak ve bağlantılı bir ağaç oluşturarak kontrol edebilirsiniz. Bunu SQL ile de yapabilirsiniz, ancak özyinelemeli alt seçimler veya çok fazla sorgu gerektirecektir. Kodunda yapsan iyi olur.

Örnek için gibi birden bağımlılıkları varsa Fire Punchbağlıdır PunchVE Immolationbağımlılık grafiği temsil etmek iki tablo kullanın:

#Talent
id  description
1   Tackle
2   Kick
3   Punch
4   Fire Punch
5   Immolation

#Depedency
id  parent  child
1   0       1
2   0       5
3   1       2
4   1       3
5   3       4
6   5       4

Kişisel UserTalenttabloda, bir autokey sütunun ihtiyacı yok. userve talentsadece iki sütun ve birleşik anahtar olabilir: bunlar asla kopya olmaz ve idyine de sorgulamazsınız .
doppelgreener

Bir veritabanı tasarımcısı değilim ve bunun hakkında söylediklerini duymak isterim: Her yeteneğin kendine özgü bir adı varsa, bu tablo tasarımındaki diğer tüm sayısal kimlik alanlarını da kaldıramaz ve isimleri anahtar olarak kullanabilirsiniz. herhangi bir düzenleme basamaklandırılmış)? Bunu yaparken herhangi bir önemli maliyet veya fayda var mıdır?
doppelgreener

3
@Jonathan Hobbs: Bir autoincrement birincil kimliği silme / güncelleme işlemleri için her zaman iyidir. Asla yavaş değildir ancak çoğu zaman daha hızlıdır. Ayrıca satır boyutu burada endişe verici değildir. Aynı şey eşsiz yetenek isimleri için de geçerlidir. İyi bir performans için, tablolarınıza yalnızca benzersiz tamsayılarla katılmak istersiniz. Bkz. En.wikipedia.org/wiki/Database_normalization vs.
Jonas Bötel

Teşekkürler. Bir keresinde tanıdığım bir DB tasarımcısı, oto anahtarların kötü olduğunu ve kaçınılması gerektiğini belirtti, ama bunun durumun ya da nedeninin olduğu konusunda hiçbir zaman net olamadım. Sanırım değil.
doppelgreener

Tasarımcılar için bir veritabanına ihtiyacınız olmadıkça, çok kullanıcılı düzenlemeyi veya başka bir şeyi desteklediğiniz için bu verileri depolamak için bir veritabanı kullanmanın gerçek bir nedeni yoktur. Aksi takdirde sadece yoluna girecek. (Bunun için asla bir birincil otomatik anahtar kullanmam, çünkü neredeyse kesinlikle DB tarafından sağlanan bir anahtar yerine bir tasarımcı tarafından karar verilen mantıksal isimlere katılmak istersiniz.)

5

Her düğümün belirli bir yetenek / beceriyi temsil ettiği bir ağaç kullanmanızı tavsiye ederim . Oyuncunun bir yetenek kazanıp kazanmadığına bağlı olarak, çocuğun yetenekleri kazanılabilir. Örneğin aşağıdaki veri yapısı

class Talent {
    std::vector<Talent*> children;
    bool earned;
};

Bir oyuncunun hangi yeteneklere sahip olduğunu belirlemek için, kök yeteneğini alır ve kazanılanların yanlış olduğu yetenek düğümlerine ulaşana kadar grafiğin içinde yürürsün. Bu aynı zamanda hangi yeteneklerin edinilebileceğini de ortaya çıkaracaktır: her daldaki ilk yetenek, kazanılan kök yeteneğinden aşağıya doğru.


Yerel bir diziye ve bir boyuta bir işaretçi var? Kendi kendine boyutlandırma işaretleme işaretçisini kullanmamak.
DeadMG

Hata! C / C ++ karışımı ve bir hata. Cevabımı güncelledim. Yardımların için teşekkürler.
hayalet

@DeadMG: 'Kendi kendine sahip olma-kendi kendine boyutlandırma' ile tam olarak neyi kastediyorsunuz? Yukarıdaki vektör gibi bir şeyden mi bahsediyorsunuz yoksa başka bir şey mi düşünüyorsunuz?
Kylotan

Bir Destek ptr_vectordaha iyi olabilir.
Zan Lynx

5
Ağaç yapısı, oyuncunun kazanıp kazanmadığından tamamen farklı olmalıdır, ilki tasarımcılar tarafından üretilen statik verilerdir ve ikincisi, tasarruflu bir oyunda veya DB'de saklanan oyuncu başına verilerdir.

1

Oyunumda şöyle yapıyorum:

Veritabanı:

reference_talent : benzersiz bir kimlik, ad, efekt vb.

yetenek : id, playerid <- oyuncuların "öğrendiği" bütün yetenekleri içerir.

Oyun içi: (sunucuda)

Reference_talents'ı 'statik' (salt okunur) std :: map içine yükledim, böylece kimlikleriyle kolayca erişebiliyorum.

Bir müşteri bir oyuncuyu kontrol ettiğinde, tüm yetenekleri veri tabanından alırım ve bunları bir std :: vector içinde toplarım, böylece özellikleri hesaplamak için ihtiyaç duyduğumda vb. Ayrıca yetenekleri müşteriye gönderiyorum.

Bu konuda (elbette 'yetenek' tablosunda sadece 'INSERT' olan + müşteriye bir mesaj olan yeni yeteneklerin kaydedilmesi dışında).


0

İlişkisel yaklaşım

Bu öğreticideki gibi kilidini açanlar ve kilidi açılmamışlar arasındaki ilişki olarak tanımlarsınız . İlişkisel cebir ve veritabanları hakkında daha fazla şey öğrenmenizi öneririm. Verileri modellemenin iyi bir yoludur. Bilgileri veritabanından nasıl sorgulayacağınızı öğrenirseniz, verileri kolayca kolayca modelleyebilirsiniz.

Modelleme ilişkileri hakkında ne biliyorsun bilmiyorum. Bu eğitim size bu konuda yardımcı olmalıdır.

Bir çözüm

WoW'nun gerçekte olduğu gibi çalıştığını (ehm), olduğunu

  • yetenek birkaç (diğer) yeteneğin kilidini açar
  • yetenek birkaç (diğer) yetenek tarafından açılmaktadır.

Bu N: N ilişkisidir; bu, iki yetenek arasında yeni bir ilişkiye "orta erkeğe" ihtiyacınız olduğunu gösterir:

(talent who unlocks id, talent who is unlocked)

Böylece A, B, C ve D ((A, B), (A, C), (A, D)) ve X, Z ve W ((X, Y), ( Z, Y), (W, Y)). Emir kipi / yordamsal / nesne yönelimli dilde, orada olduğu gibi çiftlerin listesi / listesi olarak yaparsınız:

var unlocks_unlocked = [[A, B],[A,C],[A,D],[X,Y],[Z,Y],[W,Y]];

Yani "gerçek dünya" örneği için şunları yapabilirsiniz:

... ["running fast", "jumping superhigh"], ["antigravity's child", "jumping superhigh"]

ve "hızlı koşmak" ve "yerçekimi karşıtı çocuğun" yeteneklerinden sonra "süper atlamak" anlamına geliyor.

Diğer çözüm

Son zamanlarda Diablo'yu oynamamıştım, ama olabileceği gibi, sadece vardı:

  • yetenek diğer birkaç yeteneğin kilidini açar
  • yetenek sadece bir yetenek tarafından açılabilir.

1: N ilişkisi:

 You put "is unlocked by this talent's id" variable into talent's structure

sevmek:

 var Talent[8] = { "name": "superpower", "unlocked by": "being Clark Kent"};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.