3
\$\begingroup\$

I've been thinking about the structure of an Item class. There are many items which may or may not have effects in the game.

For example, an item "Herb" has an effect to "Heal HP by 5". but an item "Stone" has no effect.

As per a title, when you design a game, how do you structure the Item class?

The following is the structure I've come up with.

class Item{
    String id;
    // Status where s = HP, MP, ATK .. etc
    // Integer -> value which affects on the Status
    Map<Status, Integer> effect;
    SignType st; // +, -, *, /
}

class Player{
    Map<Status, Integer> status; // Status where s = HP, MP, ATK .. etc
}
\$\endgroup\$
  • \$\begingroup\$ if your items are somewhat very varied in stuff they could contain and how they can be treated, maybe you should use an entity component system. \$\endgroup\$ – v.oddou Oct 14 '15 at 7:30
  • \$\begingroup\$ Related question if you want the items to have triggerable abilities or spells. \$\endgroup\$ – Anko Oct 14 '15 at 8:37
  • \$\begingroup\$ Clarification request: Are all item effects active (like "heal HP"), or are some passive (like "+10 max HP while carried")? What is the problem with your current structure? \$\endgroup\$ – Anko Oct 14 '15 at 8:38
  • \$\begingroup\$ All items effects are active at this point but, might be expanded in the future like you mentioned. \$\endgroup\$ – neko Oct 15 '15 at 0:22
  • \$\begingroup\$ well the problem is current structure cannot handle items which have no effect such as "Stone" described at the post. \$\endgroup\$ – neko Oct 15 '15 at 0:29
2
\$\begingroup\$

Have one base class Item. Then create two sub class, one for Items with effect and another for Items without effect, like this-

class Item {
    String id;
}

class EItem extends Item {
     Map<Status, Integer> effect;
     SignType st;
}

class WEItem extends Item {
}
\$\endgroup\$
  • \$\begingroup\$ This looks good. but when you check the item, you would need to use "instance of" right? and I heard it is not recommended to use it for some reasons(I forgot). It's simple yet good. \$\endgroup\$ – neko Oct 15 '15 at 0:57
  • \$\begingroup\$ This question has almost the same requirement as yours. Have a look at the answers - stackoverflow.com/questions/8841577/… \$\endgroup\$ – kazisami Oct 15 '15 at 14:48
0
\$\begingroup\$

If you want to keep things simple and each item independent, your current solution looks good. However, you only need addition and multiplication, the other two can be built with inverse operands.

In the long term, the question is if a set of predefined operations is flexible enough. What if a developer wants more sophisticated conditions, e.g.

If the item owner carries a sword, triple his attack damage.

In that case, you would need access to other items, possibly through a query interface. However, as soon as you use dynamic code, you can't easily serialize it anymore.

\$\endgroup\$
0
\$\begingroup\$

Remember that object oriented programming is usually using some form of data structure. It is probably easier to think of it in that format.

So... when creating an item. A common implementation is to just make an "onUse" function. Which... is ok, but kinda pointless. The item may have more than one effect. So... lets make it more interesting.

Class Item : {
  private:
    array<Action> ActionList;
  public:
    AddActions<Action>;
    Use(Target, Target2 = NULL){
         for( However many actions in action list)
              ActionList.onUse(Target, Target2)
    };

}

Here, our item has a target and an action list. The target is who the item is being used on. Of course you can always pass an array for multiple targets.

So...now the action list. What is an action list? If you are familiar with components, then it is basically the same thing. Action Lists are modules of code with data that is created on instantiation via factory or something.

First the interphase.

Class Action {
    virtual update(Target, Target2 = Null) =0;
}

Next the implementation.

Class RestoreHP : Action {
   private:
     _healthRestore;
   public:
     RestoreHP(HealthRestore);
     Override onUse(Target, Target2 = Null);
}
Class AddShield : Action {
   private:
     _shieldStrength;
     _shieldDuration;
   public:
     AddShield(ShieldDuration, ShieldStrength)
     Override onUse(Target, Target2 = Null);
}

When you make a new item. You add a series of Actions into it's array, and run through them.

For example... we want to make a heroic potion? Well The action list contains a heal and a shield module.

The benefit to the design is simplicity, easy to define archetypes. Easy to add more modules.

Also remember that you do not need to rebuild this class for each object of the same item. You only need to hold a reference, as the item class does not hold position.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.