Domanda

Stavo cercando un modello per modellare qualcosa che sto pensando di fare in un progetto personale e mi chiedevo se una versione modificata del modello di decoratore avrebbe funzionato.

Fondamentalmente sto pensando di creare un gioco in cui gli attributi dei personaggi sono modificati da quali oggetti hanno equipaggiato. Il modo in cui il decoratore impila le sue modifiche è perfetto per questo, tuttavia non ho mai visto un decoratore che ti consenta di abbandonare i decoratori intermedi, che è ciò che accadrebbe quando gli oggetti non sono equipaggiati.

Qualcuno ha esperienza nell'uso del motivo decorativo in questo modo? O sto abbaiando sull'albero sbagliato?

Chiarimento

Per spiegare " Decoratori intermedi " se per esempio la mia classe di base è il caffè che è decorato con il latte che è decorato con lo zucchero (usando l'esempio in Head first design pattern) il latte sarebbe un decoratore intermedio in quanto decora il caffè di base ed è decorato dallo zucchero.

Ancora più chiarimenti :)

L'idea è che gli oggetti cambino le statistiche, sono d'accordo che sto calpestando il decoratore in questo. Esaminerò la borsa dello stato. essenzialmente voglio un unico punto di richiamo per le statistiche e per farle salire / scendere quando gli oggetti sono equipaggiati / non equipaggiati.

Potrei semplicemente applicare i modificatori alle statistiche dei personaggi sull'equipaggiamento e riportarli indietro quando non sono equipaggiati. O ogni volta che viene richiesta una statistica per scorrere tutte le voci e calcolare la statistica.

Sto solo cercando feedback qui, sono consapevole che potrei usare una motosega in cui le forbici sarebbero più appropriate ...

È stato utile?

Soluzione

Ad essere onesti, sembra che tu stia davvero cercando di adattare uno schema in cui non ne hai davvero bisogno, solo per il gusto di usare uno schema. Non essere quel ragazzo.

Ora, se le armi conferissero al personaggio un po 'di forza in più / stam / CV o altro, allora potrebbe valere la pena prendere in considerazione. Ma non sembra che tu debba modificare (o decorare) le proprietà del personaggio con queste.

Altri suggerimenti

Vedo quello che stai cercando di fare, ma una delle cose da ricordare sui motivi è che non dovresti provare a calpestare il tuo disegno per adattarlo a un motivo. I motivi si verificano naturalmente - il comportamento che stai descrivendo non fa davvero parte del motivo Decoratore.

Detto questo, immagino che vorrai decomprimere un'arma tramite un ID univoco, ad esempio:

Character.unequip(LIGHTSABER);

Se dovessi provare ad adattarlo al modello Decoratore, dovresti tenere traccia degli oggetti attualmente equipaggiati e quindi, dopo aver rimosso un'arma, dovresti aggiornare il riferimento dell'oggetto che decora la LUCE LUMINOSA a quello che LIGHTSABER sta decorando. È un sacco di lavoro.

Invece, forse vale la pena considerare l'idea di @ Mitch e lasciare che le armi del personaggio siano di aiuto in una borsa di proprietà. Ricorda che un personaggio ha un set di armi. Per me, sembra che la composizione possa essere la strada da percorrere.

Ci sono tre risposte per implementare le statistiche propugnate in un videogioco:

(1) questo soddisferà qualsiasi gioco di hobbisti che tu abbia mai realizzato (e praticamente anche ogni gioco professionale):

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

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

(nota che le diverse funzioni GetStrength * () non hanno nulla a che fare l'una con l'altra)

(2) questo soddisferà tutti i giochi che non hanno la parola "diablo" nel titolo:

 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) altro

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

E onestamente (3) era probabilmente eccessivo.

Hmmm .. Sto pensando che forse un modello di comando sarebbe una buona soluzione a questo problema. Ecco cosa intendo:

Questa è la tua classe di personaggi:

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

Ecco alcuni esempi di comandi:

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

Certo, questo è solo un suggerimento e sicuramente aperto al dibattito, non sto dicendo che questo è il modo migliore o l'unico per farlo ...

Conserva solo 2 serie di statistiche, le tue statistiche di base e le tue statistiche effettive. Quando equipaggi o disequipaggi un oggetto aggiungi o sottrai dalle statistiche effettive ove appropriato. Quindi non devi attraversare l'elenco delle tue attrezzature ogni volta che vuoi sapere quali sono le tue statistiche.

So che questa domanda è vecchia, ma questo potrebbe aiutare qualcun altro se non il PO. Leggi questo articolo, per capire come questo genere di cose dovrebbe essere fatto nei giochi (da uno degli sviluppatori che hanno lavorato ai giochi Tony Hawk):

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

Componi le tue entità / oggetti di gioco. Per costruire comportamenti di entità nei giochi, mai, MAI fare affidamento sull'ereditarietà o su qualsiasi cosa che si basi sull'ereditarietà in alcun modo - questo include lo schema decorativo come suggerito dall'OP. Ti legherai le mani. La composizione è LA strada da percorrere.

Stai cercando il modello di strategia?

Perché non codificare le armi come segue:

1 = motosega 2 = fucile a pompa 4 = cannone ferroviario

Quindi ora la somma di 6 può significare solo che il personaggio possiede il fucile e la pistola. Questo è un breve riepilogo, quindi non è necessario scorrere l'elenco del dizionario delle armi. Hai ancora bisogno di una struttura per contenere le armi, ma almeno otterrai velocità con questo approccio. Ciò presuppone che tu possa avere solo un'arma per ogni categoria, ma molte categorie contemporaneamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top