0
\$\begingroup\$

This is specifically about the development and planning direction of the game development.

I'm creating a fairly basic RPG and am wondering about the approach that I should take. I've been trying to outline it all in a flow chart first, but want to see if this is a good way of going about it.

For example, I've created a class called "items", which then currently derives into "Weapons" "Armor" and "Potions". I then derive these classes further into specific types and I keep going and going, basically as specific as I want to get.

Before I get too deep into this (again, I'm still planning) - I just want to know if this is a good way of approaching this problem.

\$\endgroup\$
  • \$\begingroup\$ Don't forget to think about how these objects will be defined by tools and then loaded and constructed at runtime. Consider "data driven development" a good search term for general practices. \$\endgroup\$ – Patrick Hughes Mar 15 '18 at 21:24
3
\$\begingroup\$

It's not.

What if you want to hit with a shield (e.g. "Shield bash"), i.e. use an "Armor" as a "Weapon", or defend with a sword (e.g. "Parry") i.e. use a "Weapon" as an "Armor"?

You'll end up with having a Shield that inherits from Armor and from Weapon. And when you introduce diamond inheritance, you introduce guaranteed headaches.

Also, you'll end up a huge hierarchy, in which you could get lost, and in which you'll not want to modify base classes because it'll potentially mess up too much other features.

An issue I noted with this kind of hierarchy is when you want a feature on Armor and Weapon, but not on Potion, all of which inherit from Item: durability. To avoid code duplication, you'll write the feature in Item, but you'll also have to add the infrastructure to not use it in specific cases. As time goes by, you'll be adding feature in classes that do not exactly belong there, getting lost some more. (This is just an example tongive you the idea.)

The favoured approach is to use Composition over inheritance. Basically, you add behaviours to your items which drive what they can do. If an "Item" has an "attack" component (which has a "damage dealt" property (for instance)) , it means that you can use it as a weapon. If the same item has a "defense" component (with a "guard ratio" property, for instance), it means that the item can be used as an "armour".

Another research term is component based architecture. This should get you re-thinking your architecture :)

\$\endgroup\$
  • \$\begingroup\$ Even a lightweight DSL and a dynamic list of properties in each object with holding the script to run to handle game and system events would be better than C++ inheritance or even Interfaces in other languages. \$\endgroup\$ – Patrick Hughes Mar 15 '18 at 21:21
  • \$\begingroup\$ Component Architectures are generally the way to go, they do have some inheritance within their designs but creating discrete properties and then combining them gives you not only a Component Architecture but also the ability to go to Data Oriented (not Data Driven) design. In C++ this can be of even more benefit as the two go rather well hand in hand when systems only need to update their collections of properties.. etc... \$\endgroup\$ – James Mar 16 '18 at 8:59
2
\$\begingroup\$

Eh, that's pretty good IMO. Minecraft works that way.

I would say that you should keep your item definitions ("this is what a sword does" "this is how potions behave") as single-instance objects and the things the player sees on the ground and pick up are actually item stacks which hold information about how much damage the item has taken, how many items are in the stack, etc. and just forwards off any interactivity to the Item reference. This keeps the overhead down.

\$\endgroup\$
1
\$\begingroup\$

As you've probably seen from other answers, there are pros and cons to using a polymorphic approach.

The main two approaches to game software design fall into two broad categories:

  1. Polymorphic (inheritance based, or the "is a -" approach) object. OO purists will push this, but you have to contend with deadly diamond, amongst other potential headaches. That said, it can solve many problems very easily, and all gang of four design patterns rely on this kind of thinking to work.
  2. Composition (component based, or the "has a -" approach) objects. Each game entity has a collection of components, that define what it data is relevant to it, and what it can do. Then game subsystems which only care about certain components operate on only entities which have those components. This prevents up a lot of headaches, and completely avoids deadly diamond.

Consider the following crude example:

You want a sword that supplies your character with a built in shield: How would you do this in an inheritance based architecture. Not easily. In a component (ECS) architecture, it's simple:

Create entity: Add sword graphic component. Add combat damage component, add shield defence component.Add sword attack animation. Job done, you now have a combined sword and shield, without having to define any new classes.

In a OO architecture, this requires you to replicate code from a previously written class, resulting in code bloat, and two separate places your shield code needs to be maintained in. If you can get away with only writing code once, do so.

Personally, I would strongly advise you to research Entity Component Systems (a good tutorial is here), and then make a decision from there.

\$\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.