This is basically the issue as in Tactics for moving the render logic out of the GameObject class with the topic already discussed here and here
However I'm not really satisfied with the given answers.
What I have is an event-driven GameEngine, where each object only reacts on events happening at given GameFrames (GFs) and enqueue Events for future notifications. Example: Change state to WALKING and direction to SOUTH and enqueue event for
curGF + 10 GFs. After the Engine ticked of 10 GFs, the object is notified, updates its position and decides what to do next (start walking again, start working, disappear, ...) Note here that new state is influenced by current state and event ID.
Now each object has the simple
Draw(x, y) method which need to be implemented differently for each object while some stuff can be inherited (e.g. a pig farm lets the base class draw the building and adds a couple of animated pigs depending on current state, productivity,...)
However these 'simple' methods are quite complex and make a bad design as Drawing is coupled to the logic. Also I found animations are using a global object which I'd like to remove, but that means passing an animation 'thing' into each
But I don't see how I could possibly uncouple these things, as the drawing functions need to know quite some stuff about the objects internals (state, position, next event execution time) E.g. walk animation drawing must know that, where and how long the object is walking and the object type/sprite set to draw the object interpolated between start and end position. Also objects may be quite different, have attached decorations or goods that need to be drawn etc.
Solutions I see:
- Create an all-knowing renderer that knows how to render each object -> Not an option due to many classes and hence large dependencies
- Replacing the Draw calls by Renderer instances that render a specific object -> This would mean creating a mirrored class hierarchy which might be hard to maintain and to implement in the first place (Building->BuildingRenderer, Pigfarm->PigfarmRenderer, Mill->MillRenderer)
- Introduce basic renderers (sprite, position, animation?) that can be composited to create the final renderer for each object -> GameObjects need to push their state into those, possibly recreating/recompositing them on each update which sounds like a lot of overhead especially if an object is never rendered at all (offscreen). Also does this look very similar to the actual rendering so I doubt a real gain here but a lot of work
I don't see how I could possibly move all this out of the object classes.