Гибкая модель декоратора? - PullRequest
2 голосов
/ 09 октября 2008

Я искал шаблон для моделирования того, что я собираюсь сделать в личном проекте, и мне было интересно, подойдет ли модифицированная версия шаблона для декоратора.

В основном я думаю о создании игры, в которой атрибуты персонажей изменяются в зависимости от того, какие предметы они экипировали. Способ, которым декоратор складывает свои модификации, идеально подходит для этого, однако я никогда не видел декоратор, который позволял бы отбрасывать промежуточные декораторы, что может случиться, когда предметы не экипированы.

У кого-нибудь есть опыт использования шаблона декоратора таким образом? Или я лаю не на том дереве?

Разъяснение

Чтобы объяснить «Промежуточные декораторы», если, например, моим базовым классом является кофе, который украшен молоком, украшенным сахаром (используя пример в шаблонах дизайна «Голова первый»), молоко будет промежуточным декоратором, поскольку он украшает базовый кофе, и украшен сахаром.

Еще больше уточнений:)

Идея в том, что предметы меняют характеристики, я бы согласился, что я включаю декоратор в это. Я посмотрю в государственную сумку. по сути, я хочу, чтобы статистические данные были единым целым, и чтобы они поднимались / опускались, когда предметы были экипированы / необорудованы.

Я мог бы просто применить модификаторы к статистике персонажей при экипировке и откатить их при экипировке. Или всякий раз, когда требуется запросить статистику для всех элементов и вычислить ее.

Я просто ищу обратную связь здесь, я знаю, что я мог бы использовать бензопилу, где ножницы были бы более подходящими ...

Ответы [ 8 ]

2 голосов
/ 09 октября 2008

Я понимаю, что вы пытаетесь сделать, но одна из вещей, которую следует помнить о шаблонах, это то, что вы не должны пытаться подгонять свой дизайн, чтобы соответствовать шаблону. Шаблоны возникают естественным образом - описываемое вами поведение на самом деле не является частью шаблона Decorator.

С учетом сказанного, я думаю, вы захотите снять оружие с какого-то уникального идентификатора, скажем:

Character.unequip(LIGHTSABER);

Если вы попытаетесь вписать это в шаблон декоратора, вам нужно будет отслеживать предметы, которые в настоящее время экипированы, а затем, после удаления оружия, вам придется обновить ссылку на объект, украшающий LIGHTSABER к тому, что LIGHTSABER украшает. Это много работы.

Вместо этого, возможно, стоит подумать над идеей @ Митча и позволить оружию персонажа помочь в сумке с имуществом. Помните, что персонаж имеет набор оружия. Мне кажется, что композицией может быть путь.

2 голосов
/ 09 октября 2008

Честно говоря, звучит так, будто вы действительно пытаетесь вписать шаблон, где он вам действительно не нужен, просто ради использования шаблона. Не будь тем парнем.

Теперь, если оружие дало персонажу дополнительную силу / стойкость / л.с. или что-то еще, возможно, стоит подумать. Но это не похоже на то, что вы собираетесь изменять (или украшать) свойства персонажа с помощью них.

1 голос
/ 25 марта 2010

Я знаю, что этот вопрос старый, но это может помочь кому-то еще, если не ОП. Прочтите эту статью, чтобы понять, как на самом деле нужно делать подобные вещи в играх (один из разработчиков, которые работали над играми Tony Hawk):

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

Составляйте свои сущности / игровые объекты. Для построения поведения сущностей в играх НИКОГДА никогда не полагайтесь на наследование или на что-либо, что само по себе каким-либо образом зависит от наследования - это включает в себя шаблон декоратора, как предложено в ОП. Вы будете связывать свои руки. Композиция это путь.

1 голос
/ 12 октября 2008

Просто сохраните 2 набора статистики, базовую и эффективную статистику. Когда вы экипируете или снимаете экипировку, добавьте или вычтите из эффективной статистики, где это необходимо Тогда вам не нужно просматривать список снаряжения каждый раз, когда вы хотите узнать, каковы ваши характеристики.

1 голос
/ 11 октября 2008

Существует три ответа на внедрение расширенной статистики в видеоигре:

(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), вероятно, был излишним.

1 голос
/ 11 октября 2008

Хммм .. Я думаю, что, возможно, шаблон команды будет хорошим решением этой проблемы. Вот что я имею в виду:

Это класс вашего персонажа:

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...
 }
}

Конечно, это всего лишь предложение и определенно открытое для обсуждения, я не говорю, что это лучший или единственный способ сделать это ...

0 голосов
/ 13 октября 2008

Почему бы не закодировать оружие следующим образом:

1 = бензопила 2 = дробовик 4 = железнодорожная пушка

Так что теперь сумма 6 может означать только то, что персонаж обладает дробовиком и железнодорожным оружием. Это быстрое резюме, поэтому вам не нужно перебирать свой список словаря оружия. Вам все еще нужна какая-то структура, чтобы содержать оружие, но по крайней мере вы получите скорость с этим подходом. Это предполагает, что вы можете иметь только одно оружие каждой категории, но одновременно несколько категорий.

0 голосов
/ 12 октября 2008

Вы ищете шаблон Стратегии?

...