Assign multiple functions to array variables, then run? [Solved]

Hi,

I'm looking to create instances at different depths for an object (otest_code), where each instance of this object should be assigned a unique function which they will run.

For a controller object, I have:

GML:
ar_tf[0] = function code_1() {show_message("a")}
ar_tf[1] = function code_2() {show_message("b")}
ar_tf[2] = function code_3() {show_message("c")}



for (i = 0; i < 3; i++) {
  
    tf = instance_create_depth(x,y,i + 1, otest_code);
    tf.code = ar_tf[i];
}
Then in the step event of otest_code:

Code:
if keyboard_check(vk_left)
    {do/run/execute "code" variable}
Is there a way to do this? I know scripts can be assigned and executed via script_execute, but I'd like to avoid creating a ton of scripts for this purpose.

Thanks.
 
Last edited:
Well, there are no more "scripts" in GMS2.3, everything's a function. And yes, you can run the function stored in the array like this: ar_tf[0]();, like you would with any other function. Or simply code(); if running from inside the tf instance later in your code.
 
Last edited:

kburkhart84

Firehammer Games
Yes, you can do this. Functions created globally as you say can be assigned and ran using script_execute(). Methods are basically functions that are directly assigned to a variable, which in the case of your code has the scope of whatever object they are on. However, if you simply copy methods' references around(like you do there with tf.code = ar_tf[i], you are copying just the reference to the method. So, if you then run the method in that instance you created like code() in the step event, it will actually run like you want, sort of. The catch is that it will still have the scope of the original instance it was created on. Method variables keep their scope.

In my little MaxEase thing, I make global methods(not functions) for the easing code. They are stored in an array just like the code you have there, except that I do it in global scope. The reason I'm doing this instead of simply making functions the regular way is that I want to access them using array[index]() format since the code that is calling them receives an array index. It is shorter and quicker than using a switch statement to decide what function to call. Note that as I'm defining the array in global space in a script resource, I have to use the global. syntax to access it later(even though the definition doesn't need the global keyword since a script resource IS in global space already.

Code:
#macro FHMAXEASE_LINEAR 0
#macro FHMAXEASE_QUADIN 1
#macro FHMAXEASE_QUADOUT 2
.......
__fhEaseFunctions[FHMAXEASE_LINEAR] = function(time, start, change)
{
    return (change * time) + start;
}
__fhEaseFunctions[FHMAXEASE_QUADIN] = function(time, start, change)
{
    return (change * time * time) + start;
}
.....
That code has 31 macros, and 31 methods assigned to that global array.

Code:
function fhMaxEase(startvalue, endvalue, amount, equation)
{
    if(equation < 0 || equation > FHMAXEASE_ELASTICINOUT)
        throw("Attempted to call fhMaxEase with an invalid equation argument");
    return global.__fhEaseFunctions[equation](amount, startvalue, endvalue - startvalue);
}
That code is the one the user would call. It is a normal function. Note that I'm directly calling the method that is stored in the array just like any function, simply following the brackets with the parenthesis and arguments. The first two lines are simply making sure the equation argument is valid so it throws an exception instead of complaining about out of bounds array index error if someone does it wrong. Also, note that since the method(as opposed to function) is defined in a global variable, it will get the scope of whatever is calling it like normal functions do, even if you copy that variable around. This is different from if you create the method in an object's code.

The point of showing you this is that I think you are better off going ahead and putting code like this in a script resource instead of on objects. If you were only using it on that one object, it would make sense, but you are "passing it around" and so you have to account for scope. But if you just declare it all in global scope, you can avoid that. And doing it as methods instead of functions like I did(assigning to an array), you avoid having to use script_execute() as well.
 
Thanks @RefresherTowel. Didn't think the code block could be used like that. Works great!

@kburkhart84: Thanks for the in-depth explanation about the global scope option. For this specific case, its a one time thing where the code is simply passed once, and never referenced again, so the local approach seemed appropriate. But I do see that the global scope approach may be useful for other things that I might implement later, so thanks for bringing it up!
 
Top