21
\$\begingroup\$

I am casually working on an RPG type game in Java but I am having trouble figuring out how I can have items that can do many different things without creating a different class for every item.

As an example, how would I create an Axe that could chop trees and attack monsters?

If I extend either the chopping or the weapon class then I can't extend the other class.

If I have chopping and weapon be an interface then I will have a lot of duplicated code when a dagger can also attack monsters and a different axe can cut trees.

I am hoping there is a way to have a single Item class and load the items and their respective abilities from a file. If that is possible how can it be done? If it isn't then what is the best way to have items in a game?

\$\endgroup\$
15
\$\begingroup\$

Gregory Weir's answer is my favorite for how to structure the item instances in order to perform multiple roles.

To load from a file:

First, use YAML. YAML is a featureful data description language; it can be parsed relatively quickly, read and edited by humans, supports binary data, and libraries exist for most programming languages, including Java. This solves the "how do I get data from files into objects?"

Second, use the flyweight pattern. Most of the data you read from those files is static. It's not going to change per instance ("axe does 1d10 base damage and breaks wood but not stone" - that's true of all five axes a player has). What you actually read from the YAML files are these platonic definition, and your individual item instances have unowned (and constant) references to these, along with per-instance data like "How many swings before I break?", "Did the player give me a custom name?", and so on.

By sharing the cross-instance data in a single object, you preserve lots of memory, and make it easy to update items without persisted game state (save games or player database).

So your class structure looks something like:

  • class Item - One instance per item
    • Owns-a Weapon instance
    • Owns-a Tool instance
    • Has-a custom name, etc.
  • class Weapon - (Up to) one instance per item
    • Is-a ItemComponent
    • Refers-to WeaponDef
    • Has-a bonus enchantment level, etc.
  • class Tool - (Up to) one instance per item
    • Is-a ItemComponent
    • Refers-to ToolDef
    • Has-a durability, etc.
  • class WeaponDef - One instance per kind of weapon
    • Read from a file, fields should be constant.
    • Has-a base damage amount, 1 or 2 hands, etc.
  • class ToolDef - One instance per kind of tool
    • Read from a file, fields should be constant.
    • Has-a base durability, materials it can break, etc.
\$\endgroup\$
18
\$\begingroup\$

The Component (not Composite) design pattern is great for this purpose: http://gameprogrammingpatterns.com/component.html

Basically, an Axe would be an instance of the Item class that contained a WeaponComponent and a ToolComponent (maybe). To test if something can be used as a weapon, check if it has a WeaponComponent attached, and then talk to that WeaponComponent instance to get the item's weapon info.

Loading from a file is a separate exercise, of course.

\$\endgroup\$
  • \$\begingroup\$ And of course, once you have components you can make good use of interfaces again. Your Axe type can implement IChopper and IWeapon but can then expose the component's behavior for it, allowing you to reuse both the type and the implementation as needed and cutting out the test for components. If all axes have the same capabilities but different stats, then you're golden. If you need items to have unique abilities, you may need to implement a game-component-collection and have your update routines query the objects for what they can do via which components are present. \$\endgroup\$ – CodexArcanum Oct 15 '10 at 17:31
  • 6
    \$\begingroup\$ @CodexArcanum: "Your Axe type can implement IChopper and IWeapon but can then expose the component's behavior for it" - What's the point of this? It just bloats out your class hierarchy. The point of the component pattern is that you don't need an Axe class or an IChopper interface or an IWeapon interface, just concrete Chopper and Weapon components, and a top-level Item. \$\endgroup\$ – user744 Oct 16 '10 at 15:01
  • \$\begingroup\$ I'm currently working on a component system for my game items, and really only have one major complaint about how the pattern is used. Given the components of Weapon, Apparel, and Consumable, an item could be theoretically "corrupted" in terms of items that can't be both Weapons and Apparel, or an Apparel that is also Consumable. Logically an item can only be one "Major Component", but by restricting the components you're breaking the need for a component system all together. Thus, one of the fundamental flaws with an otherwise amazing system \$\endgroup\$ – Krythic May 10 '18 at 1:59

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.