Diablo / WoW风格的人才树应使用什么数据结构?


23

我正在考虑为在线RPG实施人才树系统,类似于在《魔兽世界》中看到的那样,在该系统中,获得技能可以解锁树中其下的下一个“层”。

有谁知道在数据库/代码中结构地实现此目标的最佳方法?

Answers:


13

使用这样的结构来表示数据库中的树:

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

另一个表格代表每个用户获得的人才

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

您可以通过查询完整的人才表并构建链接树来以编程方式检查人才依赖性。您也可以使用SQL来做到这一点,但是它将需要递归子选择或大量查询。最好在您的代码中做到这一点。

如果有多个相关性,像例如Fire Punch取决于PunchImmolation使用两个表来表示依赖图:

#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

您的UserTalent表不需要自动键列。user并且talent可以是仅有的两列和一个组合键:它们永远不会重复,您也永远不会查询id
doppelgreener 2011年

我不是数据库设计师,所以我很想听听大家的意见:如果每个人才都有一个唯一的名称,您是否也可以删除此表设计中的所有其他数字ID字段,并使用名称作为键(任何编辑级联)?这样做会产生重大成本或收益吗?
doppelgreener 2011年

3
@乔纳森·霍布斯(Jonathan Hobbs):自动递增的主ID总是很适合删除/更新操作。它永远不会变慢,但通常会更快。同样,行大小在这里也不重要。独特的人才名称也是如此。为了获得良好的性能,您只想将表连接到唯一的整数上。见en.wikipedia.org/wiki/Database_normalization
乔纳斯BOTEL

谢谢。我认识的一位数据库设计师曾经说过,自动键是邪恶的,应该避免使用,但是我一直不清楚是这种情况还是为什么。我想不是。
doppelgreener 2011年

没有真正的理由使用数据库来存储此数据,除非您需要设计人员的数据库,因为您支持多用户编辑等。否则,它将妨碍您。(我也永远不会使用主自动增量键,因为您几乎可以肯定要加入设计人员决定的逻辑名称,而不是数据库提供的键。)

5

我建议使用一棵树,其中每个节点代表一个特定的才能/技能。根据玩家是否已获得才能,可以获得其儿童才能。例如下面的数据结构

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

要确定玩家拥有哪些天赋,您可以选择根天赋并沿图走,直到到达赚取为假的人才节点。这也将揭示哪些人才可以获取:每个分支中的第一个人才,从赚钱为假的根人才开始。


您有一个指向本机数组和大小的指针吗?失败-使用自拥有的大小自定义指针。
DeadMG

糟糕... C / C ++混合和一个错误。我已经更新了答案。感谢您的单挑。

@DeadMG:“自我拥有的自我调整”到底是什么意思?您是在指上述矢量,还是在想其他事情?
Kylotan

增强ptr_vector可能会更好。
Zan Lynx

5
树形结构应与玩家是否获得树形结构完全分开,前者是设计师设计的静态数据,后者是保存在保存游戏或数据库中的按玩家数据。

1

在我的游戏中,我这样做是这样的:

数据库:

reference_talent:包含唯一的ID,名称,效果等

天赋:id,playerid <-包含玩家已“学习”的所有天赋。

Ingame :(在服务器上)

我将所有reference_talents加载到“静态”(只读)std :: map中,以便可以通过其id轻松访问它们。

当客户签出一名球员时,我会从数据库中获取所有才能,并将其存储在std :: vector中,以便在我需要计算特征等时将其存储在RAM中。我还将人才发给客户。

就是这样(当然,除了省掉新的人才,这只是表“ talent”中的“ INSERT” +给客户的消息)。


0

关系方法

您将其描述为解锁者与解锁者之间的关系,类似于本教程。我建议学习更多有关关系代数和数据库的知识。它们是如何建模数据的好方法。如果您学习如何从数据库查询信息,则可以很轻松地对数据建模。

我不知道您对建模关系了解多少。该教程应该可以帮助您。

一种解决方案

我认为《魔兽世界》的工作原理与现实一样(ehm),

  • 才能解锁数个(其他)才能
  • 人才被数个(其他)人才释放。

这是N:N关系,这意味着您需要“中间人”两个人才之间的新关系:

(talent who unlocks id, talent who is unlocked)

这样,您可以让才能A解锁B,C和D((A,B),(A,C),(A,D)),并让才能Y解锁X,Z和W((X,Y),( Z,Y),(W,Y))。在命令式/过程式/面向对象的语言中,您可以像下面那样对列表/成对数组进行操作:

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

因此,对于“真实世界”示例,您可以具有:

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

这意味着您拥有“快速奔跑”和“反重力的孩子”的才能后,就获得了“跳跃的超高”。

其他解决方案

我最近没有玩过《暗黑破坏神》,但可能只有它:

  • 才能释放其他几项才能
  • 人才只有一个人才才能解锁。

是1:N的关系:

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

喜欢:

 var Talent[8] = { "name": "superpower", "unlocked by": "being Clark Kent"};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.