GML Best way to loop through a class without using inheritance?

samspade

Member
Background, I have enemy ships and player ships. I also have missiles. Generally speaking, missiles can be fired by either the player or the enemy and I simply set a variable (target_class) in the missile so it knows which type of thing to attack.

I would do this with:

Code:
///some missile code
with (target_class) {
    //do stuff
}
where class is an object that other objects inherit from. In this case either player_parent or enemy_parent.

The problem is that I now have missiles that I want to be able to attack other missiles as well as the enemy or the player. It is much more important for my objects to inherit code than a class, so I can't really think of a good way restructure the inheritance so that it works.

I'm debating between various alternative solutions.

Option 1 - a double with loop:

Code:
with (target_class) {
    //do stuff
}
with (missile_class) {
    if (other.id != id) {
        //do exact same stuff
    }
}
This choice seems to have the advantage that it'll pretty much just work. And the disadvantage of looping through all instances twice.

Option 2 - a variable which tracks class instead of inheritance

Code:
with (destroyable_parent) {
    if (class == other.target_class) {
        //do stuff
    }
}
This advantage would require more set up, but essentially accomplish the same thing as the original. Should also just work.

Option 3 - Create and maintain my own instance lists

Code:
///create event 
//add id to class list

///clean up event
//remove id from class list

///use
for (var i = 0; i < size; i += 1) {
    //do stuff
}
This is the most flexible and I assume would be faster than with but adds a lot more overhead for me to work with, maintain, and mess up (for example I think the above code could cause errors assuming the clean up event runs immediately as it could be removed from the list causing it to skip an instance if I looped forward instead of backwards).

Any suggestions on which of these to choose, or if there are other ways how to handle it?
 

TheouAegis

Member
What all are they inheriting? I don't see why you need a player class and an enemy class. Missiles are neither players nor enemies, they're... missiles. When a missile is created, you assign it to either player team or enemy team. Don't worry about missiles inheriting code. Put code you want shared between missiles and players either in a script or user events inside the particular parents. If a missile belongs to a particular team, run that team's script or user event (using event_perform_object() to fetch the user event).

But yeah, it sounds like you need scripts more than classes.
 

samspade

Member
What all are they inheriting? I don't see why you need a player class and an enemy class. Missiles are neither players nor enemies, they're... missiles. When a missile is created, you assign it to either player team or enemy team. Don't worry about missiles inheriting code. Put code you want shared between missiles and players either in a script or user events inside the particular parents. If a missile belongs to a particular team, run that team's script or user event (using event_perform_object() to fetch the user event).

But yeah, it sounds like you need scripts more than classes.
Using inheritance for class rather than code inheritance isn't something I'm interested in (though its nice when it works out and it often does). I'd rather have a variable and check that than complicate my code and resource tree but its an interesting idea.

Edit: I decided to go with option 2 as it was the easiest to implement and seemed the lease likely to cause problems and the easiest to extend (e.g. an array of classes). But I'm still curious if anyone has other methods of looping through a 'class' that doesn't use inheritance.
 
Last edited:

samspade

Member
Just as an update, I decided to expand the system a bit. This will loop through a objects and children of an object and check them against multiple 'classes' (renamed to factions) while also allowing them to be a part of multiple 'classes'.

Code:
with (destroyable_parent) {
   
    if (id == other.id) continue;
   
    if (!is_target_faction(other.targeted_factions_array)) continue;
   
    //do stuff

}

Code:
/// @function is_target_faction(targeted_factions_array)

/// @param {array} targeted_factions_array                The array of factions to check against

/// @description Returns true if an instance is alligned with a targeted factions. 
///                       Otherwise Returns false. Must be called inside an instance 
///                       that has the my_factions_array variable.


var _targeted_factions_array = argument0;

for (var i = 0; i < array_length_1d(_targeted_factions_array); i += 1) {
    for (var j = 0; j < array_length_1d(my_factions_array); j += 1) {
            if (my_factions_array[j] == _targeted_factions_array[i]) return true;
    }
}
return false;
 
Top