5 ms·
With respect to game entities, the industry flirted with inheritance hierarchies when they started using C++ in the mid-90s, but in this decade it's mostly shif
by chipsy 17y ago
With respect to game entities, the industry flirted with inheritance hierarchies when they started using C++ in the mid-90s, but in this decade it's mostly shifted to a compositional approach where an entity is just a structure that ties together different components.
In my latest game project I made two major decisions about entities that really helped later:
-Representing entities as property lists + a unique id.
-Generating some of the entity logic based on state transition systems I make and export from QFSM.
The first part means that I can start with JSON as my map format and reuse them at runtime without a difficult "parse" step, by having the spawn code just dump more fields on top of the original object. There's some clunkiness in that I end up with a lot of potential for name collision, but so far it hasn't become something dangerously complex.
The second part is something I'm pretty proud of, as it came from the realization that the major problem with entity state is not the states themselves, but the transitions between states; those have to be kept well-formalized or you lose track very quickly. Implementation as an FSM is not exactly correct because an FSM navigates its way through the entire graph on every pass, while an entity fits better with a continuation-style approach, where on each frame it starts with a transition to use, does processing within that transition and logic to choose the next one, and then releases execution until the next frame. If I ever want to do multiple transitions in a single frame that's possible simply by calling transition() recursively.
Generating the code to choose a transition means that I barely have to think about that part: I draw up the graph, export it, and then add some lexical macros to my code to wire it up. I decided to use this system for the main loop as well as entities as it gave me more guarantees about how the code path progresses, the timing of different events, initialization/cleanup, etc., and the results were really good - the code factored itself quite naturally and I'm experiencing an absence of many types of bugs that normally haunted me in the past.
The next thing I want to try, which I'm not doing for this game, is to generate code for managing components as well; I have a lot of boilerplate for registering and unregistering the components at spawn/despawn right now, and the components aren't formalized very well; they tend to manipulate fields on the entity somewhat abusively. If I can clean that up, it'll probably be even easier to work with.