Hi SGS,
As mentioned above, it comes down to personal preference, and everyone is free to work as he or she prefers, but I am going to argue against your point! For the record: I’m sort of countering you argument because I’d like other forum visitors to get a decent overview of the matter so they can for their own opinion based on their specific needs or project.
So, that being said, I don’t see why “children accessing other children” would be an issue or a debugging nightmare, to be honest. Quite the opposite, actually, in my opinion.
First of all, for specific types of objects, I have “manager” super objects that have overview of their children. An example of this is an “enemiesManager” class. Any functionality that requires siblings to talk to each other can happen directly between two children without issue in my opinion, or can be dealt with by the manager object above these siblings. In a way, the “gun” object you mention above could also be this manager object. My manager objects deal with collective creation & removal, and all functions that need to deal with “all bullets”, or all objects managed by this object, typically held in an array.
If the issue is semantics, you have a slight point, but that is easily dealt with. You can create a simplified handle at the start of your module for objects that are referenced often, and use that in further code, like this:
local heroObject = bullet.super.super.super.super
Or if you feel the repeating “super” is confusing, you could give these classes specific names, like this:
bullet.myBulletManager.myHeroCharacter.myLevelController.myAppEngine
Second, in many parts of game programming there is little “lateral” communication ( i.e. communication between different children of the same parent) between bullets, enemies or other types of objects. 99% of the time my communication between different children of the same parent is between objects with substantially different functionality, e.g. a soundManager object (or class or module) and a levelController object.
In this case, communicating between the different children of the same parent is super-easy. My soundManager talks to the levelController like this, through their parent “appEngine” object:
self.super.levelController.finishLevel()
And my levelController talks to the soundManager like this:
self.super.soundManager.playSound()
If you feel “self.super” reads to difficultly, you can always create a more legible reference like:
myAppEngine.levelController.finishLevel()
Third and lastly, I think many alternative code architectures don’t really offer any good way of talking to siblings at all. Event and messaging systems are a substitute, but don’t offer enough control for me. Instead, If one of the child objects needs to trigger a general event, it asks it’s parent or grandparent to execture a specific part of code, and this code bubbles down to all needed objects.
This way I have a perfect overview of what objects receive “the message” first - something that is often hard to keep track of without a hiërarchical structure.
I could go on! But I’m not going to. But I can say this: for platform games, this architecture really is brilliant, and in all honesty I’ve never coded a project where this architecture did not work soooooo smoothly and easily. One of the reasons I keep going on here is that (for me) it really is a joy to work this way, and I want to spread the good word! :lol: