Diablo / WoWスタイルのタレントツリーには、どのデータ構造を使用する必要がありますか?


23

World of Warcraftで見られるものと同様のオンラインRPGにタレントツリーシステムを実装することを検討しています。スキルを取得すると、ツリーの下にある次の「ティア」のロックが解除されます。

誰もがこれをデータベース/コードに構造的に実装する最良の方法を知っていますか?

回答:


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依存関係グラフを表現するために2つのテーブルの使用:

#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そしてtalent2つの列のみと複合キーになります彼らは重複になることはありません、あなたが照会することはありませんidとにかく。
doppelgreener

私はデータベースデザイナーではありませんので、これについての意見を聞きたいと思います:すべての才能が一意の名前を持っている場合、このテーブルデザインの他のすべての数値IDフィールドも廃止できず、キーとして名前を使用できますか(カスケードされた編集)そうすることで、大きなコストや利益がありますか?
doppelgreener

3
@Jonathan Hobbs:自動インクリメントのプライマリIDは、削除/更新操作に常に適しています。遅くなることはありませんが、多くの場合は速くなります。また、ここでは行サイズは関係ありません。同じことは、ユニークなタレント名の場合にも当てはまります。良好なパフォーマンスを得るには、一意の整数のみでテーブルを結合する必要があります。参照してくださいen.wikipedia.org/wiki/Database_normalizationなど
ジョナスボーテル

ありがとう。私がかつて知っていたDBデザイナーは、オートキーは悪であり、避けるべきだと述べましたが、それが事実なのか、それとも理由なのか、はっきりしませんでした。そうではないと思います。
doppelgreener

マルチユーザー編集などをサポートしているため、デザイナー用のデータベースが必要でない限り、データベースを使用してこのデータを保存する本当の理由はありません。そうでなければ、邪魔になります。(DB提供のキーではなく、デザイナーが決定した論理名にほぼ確実に参加したいので、このためにプライマリ自動インクリメントキーを使用することもありません。)

5

各ノードが特定の才能/スキルを表すツリーを使用することをお勧めします。プレイヤーがタレントを獲得したかどうかに基づいて、その子供のタレントを獲得できます。たとえば、次のデータ構造

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

プレイヤーがどのタレントを持っているかを判断するには、ルートタレントを取得し、グラフを下って歩き、得られたタレントノードがfalseになるようにします。これにより、取得可能なタレントも明らかになります。各ブランチの最初のタレントは、獲得されたルートタレントから順に下がっています。


あなたはネイティブ配列へのポインタとサイズを持っていますか?失敗-自己所有の自己サイズ変更ポインタを使用します。
DeadMG

おっと... C / C ++の混乱とエラー。回答を更新しました。ヘッドアップをありがとう。
ゴースト

@DeadMG:「自己所有の自己サイジング」とはどういう意味ですか?上記のベクトルのようなものを参照していますか、それとも別のものを考えていましたか?
キロタン

Boost ptr_vectorはさらに良いかもしれません。
ザンリンクス

5
ツリー構造は、プレイヤーが獲得したかどうかとは完全に分離する必要があります。前者はデザイナーによって作成された静的データであり、後者はセーブゲームまたはDBに保存されたプレイヤーごとのデータです。

1

私のゲームでは、次のようにします。

データベース:

reference_talent:一意のID、名前、効果などが含まれています

タレント:id、playerid <-プレイヤーが「学習した」すべてのタレントが含まれます。

ゲーム内:(サーバー上)

すべてのreference_talentsを 'static'(読み取り専用)std :: mapにロードするため、IDで簡単にアクセスできます。

クライアントがプレーヤーをチェックアウトすると、データベースからすべての才能が取得され、std :: vectorに保存されます。そのため、特性などを計算する必要がある場合は、RAMに保存されます。また、クライアントに才能を送ります。

それはそれについてです(もちろん、新しい才能を節約することは除きます。これは、単にテーブル「talent」の「INSERT」+クライアントへのメッセージです)。


0

リレーショナルアプローチ

このチュートリアルのように、ロック解除とロック解除の関係として説明します。リレーショナル代数とデータベースについてもっと学ぶことをお勧めします。それらはデータをモデル化する良い方法です。データベースから情報を照会する方法を学習する場合データを非常に簡単にモデル化できます。

関係のモデリングについてどれだけ知っているかわかりません。そのチュートリアルはあなたに役立つはずです。

一つの解決策

私は、WoWが実際のように機能すると仮定しています(えー)

  • タレントはいくつかの(他の)タレントのロックを解除します
  • 才能はいくつかの(他の)才能によって解き放たれます。

N:N関係です。これは、2人の才能の間に「中間者」という新しい関係が必要であることを意味します。

(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"]

そして、それはあなたが「速く走る」才能と「反重力の子」の才能を持っている後に「ジャンプ超高」が得られることを意味します。

その他の解決策

私は最近Diabloをプレイしていませんが、それは次のものだけだったかもしれません:

  • タレントは他のいくつかのタレントのロックを解除します
  • 才能はたった1人の才能によって解き放たれます。

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"};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.