I would suggest to delay the call of the init() function on an entity until all entities are spawned. The problem is that you can not (savely) access other entities within the init function which makes one-time initializations involving multiple entities problematic.
From my point the init() function is a one time initialization when a level is loaded. However right now it is but a mere constructor. If that constructor behavior is intended I would suggest a second initialization method, something like "initEntity", "start" or "first"(-update).
My use case:
Right now I'm trying to link multiple entities to a ragdoll. The code for creating the Box2D joints is in the init function of the torso. However when the torso is spawned the other entities (arms, legs) have not been spawned yet and are not accessible through ig.game.getEntityByName.
Workaround:
Move that initialization code to the update() method and check a flag if this is the first call to update().
What do you guys think? Anyone else stumbled into that problem?
Cheers, Rick
1 decade ago
by Arantor
I get the feeling you're using the init in a way that it isn't designed to be.
In any other language, you couldn't reference the arms from the torso if they haven't been instantiated yet, this is the same problem.
Surely, you'd do what you'd do in any other language or environment, spawn everything and have it attach hierarchically, nearest first?
IOW, spawn the torso, then spawn the arms/legs, then join them together. Or spawn the legs first in place (on the ground) and then spawn the torso joining to the legs, whichever works for you.
First, I'm aware that I can't access an entity that has not been created yet.
However that is my point. It would be more practical if all entities have been created before init() is called on the entities.
To clarify, I have placed all entities (head, torso, arms, legs) within a level through Weltmeister. When Impact loads that level it creates/spawns all entities in the order that they have been created in Weltmeister. When an entity is spawned, the init() method is called, however at this point obviously not all entities may have spawned yet.
Maybe I should move that code out if the torso entity anyway. I guess I could create a Impact module and put that code into the module. Then I would call that code after I have loaded a level.
1 decade ago
by Arantor
Hmm, I didn't think you'd create each entity separately in the editor. It seemed more logical to me that you'd place one entity at most and then have the remaining entities spawn around it according to their behaviour and do that programmatically (which is why I was having something of a hard time understanding what the problem was)
I wouldn't put it in the update routine, that's asking for performance issues (because an update is evaluated every frame IIRC, as opposed to during initialisation only)
You could, I guess, have each of the torso, arms and legs call a common routine in their init (perhaps create your own EntityBodyPart with it and then extend that) so that no matter what order they're created in, they can check for the existence of other parts and do whatever joining is necessary.
On the broader case, I can see the logic behind deferring the init call, insofar that for your specific case (entities that need to be spawned in a particular order that may not be called in the right order by the editor) it would be a neat idea. The implementation, on the other hand, is a different beast entirely, since it would require a fair-sized overhaul to the Entity object. (The Entity class derives all its behaviour from the Class object, just like everything else in Impact, one of the behaviours of which is to call its init function automatically on instantiation.)
I wouldn't want an entity subclass to know how to stitch itself to others. Conceptually, I'd rather make my level object or game the stitcher, or better yet have a pluggable helper class (Rigger) do the rigging.
Maybe this:
MyGame = ig.Game.extend(
{
loadLevel: function (levelObject)
{
this.parent (levelObject);
// rig my rag
Rigger.attach(neck, torso, ANCHOR, ig.world);
Rigger.attach(head, neck, ANCHOR, ig.world);
}
});
I mean, wouldn't all entities have been initialized by the time ig.Game.loadLevel was done?
@Arantor
Yeah, placing all entities in the editor probably wasn't the best idea either. Seems I can't move them as a group, plus I would have to set them up in each level - or have some sort of level template. I'm going to create them in code now. Thanks for the input!
@alexandre
You're right, some sort of helper module might be the cleanest solution here. Also overriding loadLevel() could be very useful in my case, as I could also spawn my entities here manually. And yeah, after loadLevel() is called, all entities of the level are created and initialized.
1 decade ago
by gxxaxx
Something I have done that works for me is to overload the loadLevel.
Then after the parent call use something like the following:
loadLevel: function(data) {
this.parent(data);
for( var i = 0; i < this.entities.length; i++ ) {
var ent = this.entities[i];
if( ent._killed || typeof(ent.postInit) != 'function') {
continue;
}
ent.postInit();
}
I can leave my init methods as they should be without messy inter entity dependencies.
Then after all entities have been through init (natural process of instantiation), then I call this postinit function (if it exists).
One of the advantages of this is that I can put any code that relies on being in a game (as opposed to the edit) in the postinit.
Don't know how well this fits into best practices, but it works for me.
Page 1 of 1
« first
« previous
next ›
last »