In many games, it's typical to load in several 'concepts' or 'definitions' from the data - for example, you might load in vehicle types, character classes, item types, etc. This data might be passed to some sort of factory which creates one of several related classes each time. And then in-game, you create instances of these concepts - vehicles, individual characters, individual items, etc. These will reference the definition class to get access to various pieces of data.
But where it seems to get tricky is when the instances are used in some sort of algorithm, and need their own set of state data, which might vary depending on the concept being referenced. If you can have fully-generic concepts, or fully-generic instances, it's not an issue. But often you don't, and the specifics of the instance may depend on the specifics of the concept.
I can think of several ways to approach this in C++, but none of them are fully satisfactory.
- If there's one generic 'instance' shared across all related concepts, it needs to accommodate all possible state, which is awkward to maintain. (eg. the Vehicle object might need current_gear for cars, landing_gear_down for planes, rudder_position for boats, etc etc.)
- if there's a generic data store used as the state data - eg. a std::map of key/value objects - then it will work for any case... if you don't mind all the error-checking in the definition to ensure important keys exist, and to ensure the values are the right type, etc.
- If there's a separate instance class for every concept class, it's error-prone. You have to be very sure to create them properly and then several parts of the instance class need to perform casts to the assumed type.
- If the definition class is re-used as the instance class - e.g. using the Prototype pattern - then you have one C++ class essentially handling 2 responsibilities. The part of the code dealing only with definitions has several state variables it doesn't need to touch, and the part dealing only with instances has several definition variables it shouldn't touch. Plus it wastes memory to duplicate the definition in that way.
This does seem like a problem lots of intermediate-level development will face. How are people handling issues like this?
(Edit: there's a good article on gameprogrammingpatterns.com about this, but it basically just agrees that behaviour becomes more difficult: http://gameprogrammingpatterns.com/type-object.html#it%27s-harder-to-define-behavior-for-each-type)