• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Get List of Child Objects for a Parent Object

T

Thurnok

Guest
Did a few search algorithms for this, but nothing came up that was what I was looking for, so...

Just wondering if there is a way to "programmatically" get the list of Child Objects a Parent Object contains? I know you can see the list in the Object editor, but I'd like to be able to get a list (in code) of the children for a parent. To explain why, what I wish to do is the following:

Create a parent object to contain the majority of functionality for all the child objects I create under it. Then create several child objects which may or may not have unique functionality, but have different sprites. Within a game room, add child objects where I specifically want "that" particular type of the object, but in addition, place the parent object in locations where I want to then have one of its children selected randomly at creation time to replace it ( instance_change() for example ).

I don't want to "statically" create a list of the child objects, because then in the future, if I add more child objects, I have to change the code to include those newly added child objects in the list. Rather, I would like to have the randomized code not have to change, by being able to grab the list of child objects to then randomly select from. This means I could add more child objects down the road and not have to update the code itself.

For example...

Create event for Parent object:
- check if this is the parent object as opposed to a child ( maybe: par = object_get_parent(object_index); )
- then, if par = -100 it is the parent object, not one of the children, so...
- get the list of children this parent has
- then select random(count children) + 1
- grab that numbered item from the list of children
- instance_change(the child item, true) // run destroy for parent, create for child

- if it is a child instead of the parent, possibly do other things here in the create event...


So being able to programmatically get the list of child objects then allows me to down the road add 30 more child objects without having to change the above code at all. Is there a way to do this currently (I didn't see one)? If not, anyone have a suggestion for a workaround to perform something similar (again without having to change code every time I add new child objects)?
 

Alice

Darts addict
Forum Staff
Moderator
I don't think there's a built-in way to get children in the hierarchy of objects, but you might obtain it by using map, lists and a trick.

Generally, the first object in resource tree has an index of 0, and all subsequent objects have index one larger than the previous one. You can also check if an object with a given index exists, by using object_exists. So, you can enumerate objects by going from 0, until an object with a given index doesn't exist.

Once you are able to enumerate the objects, you are in a good position to build the hierarchy of them. You can do that with object_get_parent.

Now, to put two and two together...
Code:
// run that once, at the very beginning of the game
// the objects hierarchy will be then quickly available for the rest, as long as you don't change it

global.hierarchy = ds_map_create();
var obj = 0;
var parent;

for (var obj = 0; object_exists(obj); obj++)
{
    // adding a new list assigned to the object, if needed
    if (!ds_map_exists(global.hierarchy, obj)) ds_map_add_list(global.hierarchy, obj, ds_list_create());

    // this will populate parent's list with direct children
    parent = object_get_parent(obj);
    if (object_exists(parent))
    {
        if (!ds_map_exists(global.hierarchy, parent)) ds_map_add_list(global.hierarchy, parent, ds_list_create());
        ds_list_add(global.hierarchy[? parent], obj);
    }

    // this will populate parent's list with all descendant objects
    // if you want to use that variation instead, remove the direct children variation
    /*
    parent = object_get_parent(obj);
    for (parent = object_get_parent(obj); object_exists(parent); parent = object_get_parent(parent))
    {
        if (!ds_map_exists(global.hierarchy, parent)) ds_map_add_list(global.hierarchy, parent, ds_list_create());
        ds_list_add(global.hierarchy[? parent], obj);
    }
    */
}
Then you can access a random child of a given parent object like that:
Code:
var children = global.hierarchy[? object_index];
var child = children[| irandom(ds_list_size(children)-1) ];
Hope this helps. ^^
 
T

Thurnok

Guest
That is most excellent Alice!

Given that the resource tree indexing works the way you mentioned, I'm embarrassed I didn't think of that myself. I'm a long time developer (ASM, C++, Delphi, among others), but relatively new to GM as I've had it "on the shelf" for years, finally deciding to "dust it off".

I am surprised given the object editor has a "children" list box it auto-populates, that GM doesn't have a Child or Children property for an object accessible via code. Seems like it would make sense, but such as it is, your solution is perfect and very much appreciated!

And might I add, very quickly responded to as well. Thank you.
 
Top