2

個人的なプロジェクトでやろうと考えていることをモデル化するためのパターンを探していましたが、デコレータ パターンの修正版が機能するかどうか疑問に思っていました。

基本的には、キャラクターが装備したアイテムによって属性が変化するゲームを作ろうと考えています。デコレーターが変更をスタックする方法はこれに最適ですが、中間のデコレーターをドロップできるデコレーターを見たことがありません。これは、アイテムが装備されていないときに起こることです。

この方法でデコレータ パターンを使用した経験がある人はいますか? それとも、間違った木を吠えていますか?

明確化

たとえば、私の基本クラスが砂糖で装飾されたミルクで飾られたコーヒーである場合、「中間デコレーター」を説明するには (Head first design patterns の例を使用) ミルクは、ベース コーヒーを装飾し、装飾されるため、中間デコレーターになります。砂糖によって。

さらに明確化:)

アイデアは、アイテムが統計を変更するということです。これにデコレータを押し付けていることに同意します。ステートバッグを調べてみます。基本的に、私は統計の単一の呼び出しポイントと、アイテムが装備されている/装備されていないときにそれらが上昇/下降することを望んでいます。

装備時にモディファイアをキャラクターの統計に適用し、装備を外すときにそれらを元に戻すことができました。または、統計が要求されるたびに、すべてのアイテムを繰り返し処理して統計を計算します。

ここでフィードバックを探しているところです。ハサミの方が適切なチェーンソーを使用している可能性があることは承知しています...

4

8 に答える 8

2

正直なところ、パターンを使用するためだけに、実際には必要のないパターンに合わせようとしているように思えます。その男にならないでください。

さて、武器がキャラクターに追加の強さ/スタム/HPなどを与えるなら、それは検討する価値があるかもしれません. しかし、これらを使用してキャラクターのプロパティを変更 (または装飾) するつもりはないようです。

于 2008-10-09T11:32:41.017 に答える
2

あなたがやろうとしていることはわかりますが、パターンについて覚えておくべきことの 1 つは、パターンに合わせてデザインを靴べらにしようとしてはならないということです。パターンは自然に発生します。説明している動作は実際には Decorator パターンの一部ではありません。

そうは言っても、一意のIDを介して武器を装備解除したいと思うでしょう。たとえば、次のようにします。

Character.unequip(LIGHTSABER);

これを Decorator パターンに当てはめようとすると、現在装備されているアイテムを追跡する必要があり、武器を取り外した後、ライトセーバーを装飾しているオブジェクトの参照を更新する必要があります。ライトセイバーが飾っています。それは大変な作業です。

代わりに、@Mitch のアイデアを検討する価値があり、キャラクターの武器をプロパティ バッグで使用できるようにすることをお勧めします。キャラクターには一連の武器があることを思い出してください。私には、コンポジションが進むべき道のように思えます。

于 2008-10-09T11:39:46.073 に答える
1

私はこの質問が古いことを知っていますが、これはOPではないにしても他の誰かを助けるかもしれません. この記事を読んで、ゲームでこの種のことを実際にどのように行うべきかを理解してください (Tony Hawk ゲームに取り組んだ開発者の 1 人による):

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

エンティティ/ゲーム オブジェクトを構成します。ゲームでエンティティの動作を構築するために、継承に依存したり、継承に依存するものに依存したりしないでください。これには、OPが提案したデコレーターパターンが含まれます。あなたは自分の手を縛ることになります。構成は行く方法です。

于 2010-03-24T23:26:17.850 に答える
1

ビデオ ゲームに伝播統計を実装するには、次の 3 つの答えがあります。

(1) これは、あなたが作るホビストゲームを満足させます (そしてほとんどすべてのプロのゲームも同様です):

character.GetStrength() {
  foreach(item in character.items)
    strFromItems += item.GetStrengthBonusForItems();
       foreach(buff in character.buffs)
    strFromBuffs += buff.GetStrengthBonusForBuffs();
  ...

  return character.baseStrength + strFromItems + ...;
}

(異なる GetStrength*() 関数は互いに何の関係もないことに注意してください)

(2) これは、タイトルに「diablo」という単語が含まれていないすべてのゲームを満たします。

 character.GetStr() { ... // same as above, strength is rarely queried }
 character.GetMaxHP() { 
   if (character._maxHPDirty) RecalcMaxHP();
   return character.cachedMaxHP;
 }
 // repeat for damage, and your probably done, but profile to figure out
 // exactly which stats are important to your game

(3) その他

 // changes in diablo happen very infrequently compared to queries, 
 // so up propegate to optimize queries.  Moreover, 10 people edit 
 // the stat calculation formulas so having the up propegation match 
 // the caculation w/o writing code is pretty important for robustness.

 character.OnEquip(item) {
     statList.merge(item.statlist);
 }

 character.GetStrength() {
     statList.getStat(STRENGTH);
 }

 statlist.getStat(id) {
     if (IS_FAST_STAT(id)) return cachedFastStats[id];
     return cachedStats.lookup(id);
 }

 statlist.merge(statlist) {
      // left for an exercise for the reader
 }

そして正直なところ、(3) はおそらくやり過ぎでした。

于 2008-10-11T19:15:16.497 に答える
1

うーん..おそらくコマンドパターンがこの問題の良い解決策になると思います。これが私が意味することです:

これはあなたの文字クラスです:

Public class Character {

 //various character related variables and methods here...

 Command[] equipCommands;
 Command[] unequipCommands;

 public Character(Command[] p_equipCommands, Command[] p_unequipCommands) {

  equipCommands = p_equipCommands;
  unequipCommands = p_unEquipCommands;
 }

 public void itemEquiped(int itemID) {

  equipCommands[itemID].execute(this);
 }

 public void itemUnequiped(int itemID) {

  unequipCommands[itemID].execute(this);
 }
}

コマンドの例を次に示します。

public class SwordOfDragonSlayingEquipCommand implements ItemCommand{

 public void execute(Character p_character) {

  //There's probably a better way of doing this, but of the top of my head...
  p_character.addItemToInventory(Weapons.getIteM(Weapons.SWORD_OF_DRAGON_SLAYING));

  //other methods that raise stats, give bonuses etc. here...
 }
}

public class SwordOfDragonSlayingUnequipCommand implements ItemCommand{

 public void execute(Character p_character) {

  //There's probably a better way of doing this, but of the top of my head...
  p_character.removeItemFromInventory(Weapons.getIteM(Weapons.SWORD_OF_DRAGON_SLAYING));

  //other methods that lower stats, remove bonuses etc. here...
 }
}

もちろん、これは単なる提案であり、間違いなく議論の余地があります。これが最善または唯一の方法だと言っているわけではありません...

于 2008-10-11T12:33:56.090 に答える
1

基本ステータスと有効ステータスの 2 セットのステータスを保持するだけです。アイテムを装備または装備解除すると、必要に応じて有効な統計に加算または減算されます。そうすれば、自分の統計が何であるかを知りたいと思うたびに、機器リストをトラバースする必要がなくなります。

于 2008-10-12T13:18:39.010 に答える
0

次のように武器をコーディングしないでください。

1 = チェーンソー 2 = ショットガン 4 = レールガン

したがって、6 の合計は、キャラクターがショットガンとレールガンを所有していることを意味するだけです。これは簡単な要約なので、武器の辞書のリストを反復処理する必要はありません。武器を格納するための構造が必要ですが、少なくともこのアプローチでスピードを得ることができます。これは、各カテゴリの武器を 1 つしか持てないが、同時に多くのカテゴリを持つことができることを前提としています。

于 2008-10-13T00:45:31.743 に答える
0

戦略パターンをお探しですか?

于 2008-10-11T20:52:09.203 に答える