Pregunta

Estaba buscando un patrón para modelar algo que estoy pensando hacer en un proyecto personal y me preguntaba si una versión modificada del patrón de decorador funcionaría.

Básicamente estoy pensando en crear un juego donde los atributos de los personajes se modifiquen por los elementos que hayan equipado. La forma en que el decorador apila sus modificaciones es perfecta para esto, sin embargo, nunca he visto un decorador que le permita soltar decoradores intermedios, que es lo que sucedería cuando los elementos no estén equipados.

¿Alguien tiene experiencia usando el patrón decorador de esta manera? ¿O estoy ladrando el árbol equivocado?

Clarificación

Explicar " Decoradores intermedios " si, por ejemplo, mi clase base es café que está decorado con leche que está decorada con azúcar (usando el ejemplo en los patrones de diseño de Head first), la leche sería un decorador intermedio ya que decora el café base y está decorado con azúcar. p>

Aún más aclaraciones :)

La idea es que los elementos cambien las estadísticas, estoy de acuerdo en que estoy arreglando el decorador para esto. Revisaré la bolsa del estado. esencialmente quiero un único punto de referencia para las estadísticas y para que suban / bajen cuando los artículos están equipados / no equipados.

Podría aplicar los modificadores a las estadísticas de los personajes al equiparlos y hacerlos retroceder cuando no estén equipados. O cada vez que se solicita una estadística, recorra todos los elementos y calcule la estadística.

Solo estoy buscando comentarios aquí, soy consciente de que podría estar usando una motosierra donde las tijeras serían más apropiadas ...

¿Fue útil?

Solución

Para ser honesto, parece que realmente estás tratando de ajustar un patrón donde realmente no necesitas uno, solo por el simple hecho de usar un patrón. No seas ese tipo.

Ahora, si las armas le dieron al personaje algo de fuerza / stam / hp extra o lo que sea, entonces vale la pena considerarlo. Pero no parece que vayas a modificar (o decorar) las propiedades del personaje con estos.

Otros consejos

Veo lo que estás tratando de hacer, pero una de las cosas que debes recordar sobre los patrones es que no debes tratar de calzar tu diseño para que se ajuste a un patrón. Los patrones ocurren de forma natural: el comportamiento que está describiendo no es realmente parte del Patrón de decorador.

Dicho esto, me imagino que querrás deshacer un arma con una identificación única, por ejemplo:

Character.unequip(LIGHTSABER);

Si intentaras encajar esto en el Patrón Decorador, deberías hacer un seguimiento de los elementos equipados actualmente y luego, después de quitar un arma, deberías actualizar la referencia del objeto que decora el LIGHTSABER al que LIGHTSABER está decorando. Eso es mucho trabajo.

En cambio, quizás valga la pena considerar la idea de @ Mitch y dejar que las armas del personaje sean de ayuda en una bolsa de propiedades. Recuerda que un personaje tiene un conjunto de armas. Para mí, parece que la composición puede ser el camino a seguir.

Hay tres respuestas para implementar estadísticas proyectadas en un videojuego:

(1) esto satisfará cualquier juego de hobbist que hagas (y casi todos los juegos profesionales también):

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

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

(tenga en cuenta que las diferentes funciones GetStrength * () no tienen nada que ver entre sí)

(2) esto satisfará todos los juegos que no tengan la palabra 'diablo' en el título:

 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) más

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

Y honestamente (3) probablemente fue exagerado.

Hmmm ... Estoy pensando que tal vez un patrón de comando sería una buena solución para este problema. Esto es lo que quiero decir:

Esta es tu clase de personaje:

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);
 }
}

Aquí hay algunos ejemplos de comandos:

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

Por supuesto, esto es solo una sugerencia y definitivamente está abierto a debate, no estoy diciendo que esta sea la mejor o la única forma de hacerlo ...

Solo mantén 2 conjuntos de estadísticas, tus estadísticas base y tus estadísticas efectivas. Cuando equipe o desembale un elemento, sume o reste de las estadísticas efectivas cuando corresponda. Entonces no tiene que recorrer su lista de equipos cada vez que quiera saber cuáles son sus estadísticas.

Sé que esta pregunta es antigua, pero esto podría ayudar a alguien más si no es el OP. Lea este artículo para comprender cómo se debe hacer este tipo de cosas en los juegos (por uno de los desarrolladores que trabajaron en los juegos de Tony Hawk):

http://cowboyprogramming.com/2007/01/05/ evolucione su heirachy /

Componga sus entidades / objetos del juego. Para construir comportamientos de entidad en los juegos, nunca, NUNCA confíe en la herencia, ni en nada que se base en la herencia de ninguna manera; esto incluye el patrón decorador como sugirió el OP. Estarás atando tus propias manos. La composición es EL camino a seguir.

¿Está buscando el patrón de estrategia?

¿Por qué no codificar las armas de la siguiente manera?

1 = motosierra 2 = escopeta 4 = cañón de riel

Entonces, la suma de 6 solo puede significar que el personaje posee la escopeta y la pistola de riel. Este es un resumen rápido para que no tenga que recorrer su lista de diccionarios de armas. Todavía necesitas algo de estructura para contener las armas, pero al menos obtendrás velocidad con este enfoque. Esto presupone que solo puede tener un arma de cada categoría, pero muchas categorías simultáneamente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top