I'm programming an interface over pygame as a personal project, to make the creation of games easier for me.
So far I managed to design an architecture that behaves like this :
- Objects are displayable components that can appear and move on the screen
- Objects can have children objects
- When an object displays itself, it ask all his children to display themselves on the parent's surface.
- Objects have three important elements : a callback system, a graphics system and a physics system to respectively act, display and move.
Then, when I want to create a game "scene", I create a "root" object that contains other objects like the player, the mouse, the ground, monsters...
Then I just have to ask the root to display itself, and every object appears recursively.
I designed this without knowing about the composite pattern at first, only the basics of OOP.
My main issue was to make the substitutability property of objects that comes from inheritance to work well with the recursive composition I made.
I mean that I have an "abstract" class called "Object" (I put abstract into quotes because Python doesn't really have such concept) that is inherited by classes like "Image" (to be able to display) or "MovingObject" (to be able to move). Here, inheritance is meant to extend my object abilities.
But my composite pattern requires that "groups of objects must be considered the same as single objects".
So when I call recursively a method from an object, it calls that method from every child of the object, regardless of the fact that some of them may not have that method.
For instance, let's use this root element :
- root (Image)
- player (MovingObject)
- cloud (MovingObject)
- background (Image)
- sun (Image)
Now let's suppose we want to call the method
move() on the root element, to make every child move : First, we cannot because root is an Image instance, so it doesn't know the
move() method. But even if it was the case, the children "background" and "sun" would not know it.
So I decided to put an empty method
move() inside my "abstract" Object class, so every object knows it, even if it doesn't do anything.
The issue is that my Object class is now containing empty methods that it doesn't understand nor needs, only to permit the recursive behavior.
Then I heard about all the "inheritance vs composition" fuss and one of the solutions that came to my mind was to stop using inheritance for Object abilities and use composition instead. That means I would create, for example, a "Body" class, an "Image" class and a "Callback" class that would represent different actions, and then plug these into an Object instance to "equip" it and give it more power.
But then I thought that this will barely change something because I will have to call
move(), and then the object will check if it has the Body plug-in, and use it. But it still requires the
move() method to be present inside the Object class.
So I'm turning to you guys to gave me advices about my pattern :
- Did I understand well how the composite pattern works ?
- Is my approach correct ?
- Does the use of "plug-in" classes will help me ?
- Is the recursive behavior a good idea ?
- Is there other patterns that are more fitting to my needs ?
I hope you can give me some hints!