GMS 2 Scripts drawing surfaces, memory leak.

So originally I've got 16 sets of this code block messily creating a surface each all within a single draw event; since they're all similar blocks I decided to figure out scripts and tidy it up since the variables are easy enough. I translated it directly into a script with no changes in logic.

(Bear in mind the code worked fine before, I just wanted to learn+tidy)

So I am calling this script from my draw event (obj\_roof\_surface)
GML:
function scr_set_roof_surface(argument0,argument1,argument2)

    {

    

     if !surface_exists(argument1)

    {

     argument1 = surface_create(global.vw*1.2,global.vh*1.2)

    }

    

    surface_set_target(argument1);

    draw_clear_alpha(c_black,0)

    gpu_set_blendmode(bm_normal);

    

    

    var lay_id = layer_get_id(argument0); //get layer id to grab for draw

    var map_id = layer_tilemap_get_id(lay_id);

    if !(keyboard_check(vk_space))

     {

      gpu_set_blendmode(bm_normal)

      draw_tilemap(map_id,-round(global.avx),-round(global.avy)); //draw at 0 but subtract the view coords

      gpu_set_blendmode(bm_normal)

      

     }

         //draw glow

        with(obj_player)

            {

                gpu_set_blendmode(bm_subtract);

       draw_sprite_ext(spr_light,0,x-round(global.avx),y-round(global.avy),sight_size,sight_size,0,c_black,1);

       draw_circle_colour(x-round(global.avx),y-round(global.avy), 50, c_white, c_black, 0);

       gpu_set_blendmode(bm_normal)

    

            }

    

    draw_set_alpha(argument2)

    surface_reset_target();

    draw_surface(argument1,round(global.avx),round(global.avy));

    draw_set_alpha(1)

    

    }
with

GML:
scr_set_roof_surface("Roof_A", roof_b, global.roof_a_alpha)
Now it "*appears*" to work, but even with only one script it quickly accumulates megabytes of memory until it slows to a crawl. I assume it's recreating the surface every step or something? I was of the impression scripts could use the variables from within the object that they were called so why is this happening?

I tried variations of drawing and setting targets before or/and after the call script event but weird things are now happening with the surface; and it just doesn't seem right.

I'm very, very confused. Should I be using global surfaces or just avoid creating surfaces within scripts all together?

To clarify, in my obj create event I set the surface variable up

roof_a = -1

Any help is appreciated cause I don't know how to move this forward really

Thanks
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Moderator
argument1 is NOT setting the roof variable to the surface ID. You can't pass variable IDs around like that, only variable VALUES. So you need to remove argument1 and set the roof_a variable to the script ID directly. The only alternative would be to pass the variable name as a string, then use the variable functions to retrieve the actual variable to set, but that seems like overkill.
 
Ah okay I'll try that when I get home, thanks.

I'm trying to imagine what it looks like to get the surface ID from a string? How do I return a surface ID at all for that matter, is the ID what is stored as a value in the variable? If so, then how is this different to just calling it from argument1?

So as i understand it, each time the script is called and I use roof_a, it just considers that to be equivalent to = -1 (non existing) and creates a surface in response.

Is it also an alternative to set roof_a as a global surface so it can be accessed directly by the script?
 

TailBit

Member
You tell the script the name of the variable, then you use the variable_ functions to get/set the surface id to it
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Moderator
So as i understand it, each time the script is called and I use roof_a, it just considers that to be equivalent to = -1 (non existing) and creates a surface in response.
That's exactly the issue!

Is it also an alternative to set roof_a as a global surface so it can be accessed directly by the script?
Yes, indeed! Although I think the safest solution would be to simply remove the surface_exists check from the function then do that check before calling it... You would then supply the surface ID itself to the function instead of the variable that stores the ID, if that makes sense? So, before you call the function, you define roof_a (or whatever) and check if the surface exists or not, and if it DOES exist, then call the function, passing in roof_a (or whatever) knowing that it holds a surface ID and not -1. If it doesn't then you create the surface and next step the function will be called.
 

jonjons

Member
Ah okay I'll try that when I get home, thanks.

I'm trying to imagine what it looks like to get the surface ID from a string? How do I return a surface ID at all for that matter, is the ID what is stored as a value in the variable? If so, then how is this different to just calling it from argument1?
off topic, you may be getting confused... for the script y are using...
in a script var aa = argument, return value, etc... is ( obsolete ) its been obsolete since 1.4, its for compatability reasons...

For better use of the function you use your object variables ( surfaces, speed, bullets, score, etc... )
variable_instance_set

GML:
function GunOut(inst_var, value1)
{
    variable_instance_set(id, inst_var, value1);
}

//---playet-setp-eve---
if keyboard_check_pressed(ord"H")
{
    GunOut ("machineGun12345", ! holter);
}
 
Last edited:

gnysek

Member
To re-assign surface ID to global. variable, you can use return.

GML:
function scr_set_roof_surface(argument0,argument1,argument2) {

    var _surf = argument1;

    if !surface_exists(_surf)
    {
         _surf = surface_create(global.vw*1.2,global.vh*1.2)
    }

   surface_set_target(_surf);
   ...
   return _surf;
}
GML:
global.roof_a_alpha = scr_set_roof_surface("Roof_A", roof_b, global.roof_a_alpha);
 
Top