GameMaker [Solved] object variables and dynamic resources

B

basement ape

Guest
Hey all,

To get around a problem with alpha-blending on interpolated sprites I am creating new, dynamic sprite objects from within another object.

Like this:

(Create event):
Code:
global.layer_BG = layer_create(objDepth, "Instances");
layer_add_instance(global.layer_BG, self);

bck_X = x;
bck_Y = y;


// for CRT mode we need to create a new sprite from a fully opaque sprite and a separate alpha channel sprite.
// The reason being that GMS2 will blend transparent regions to black on upscaling filtered sprites, leaving
// them with visible black outlines if we just draw them as normal.

var dynsurf = surface_create(316, 324);
surface_set_target(dynsurf);
   draw_sprite(spr_forest_bigtree1_bg1_CRT, 0, 0, 0);
   gpu_set_blendmode(bm_subtract);
   draw_sprite(spr_forest_bigtree1_bg1_alpha, 0, 0, 0);
   gpu_set_blendmode(bm_normal);
surface_reset_target();

dyn_spr_forest_bigtree1_bg1_CRT = sprite_create_from_surface(dynsurf, 0, 0, 316, 324, false, true, 0, 0);

surface_free(dynsurf);
(Draw event):
Code:
if global.CRT_Mode == false
{ draw_sprite_ext(spr_forest_bigtree1_bg1, 0, bck_X, bck_Y, 1, 1, 0, c_white, 1); }

else if global.CRT_Mode == true
{ draw_sprite_ext(dyn_spr_forest_bigtree1_bg1_CRT, 0, bck_X, bck_Y, 0.5, 0.5, 0, c_white, 1); }
These objects are used to draw all kinds of level graphics; floor tiles, backgrounds etc. This here is for a big tree with the pointer 'dyn_spr_forest_bigtree1_bg1_CRT' for the dynamically created sprite.

The problem with this code is that every single instance will create a new dynamic sprite in their Create event, which will waste a lot of memory.

I'd like for the first instance to create a dynamic sprite within the Create event, and then for any other instances created after it to reference the first one's sprite instead of creating their own.

I'm not sure how to go about that tho. I tried doing 'if !instance_exists(obj_forest_bigtree1.dyn_spr_forest_bigtree1_bg1_CRT) { // create new sprite }' without any luck.

Anyone able to help me out?
 
I

icuurd12b42

Guest
that is a really bad idea

first, you should not do graphics related stuff outside the draw event
second, this will be so slow not only creating all those sprites but using them, even if you create one shared sprite per same object instance... your texture page swaps will got through the roof...

irrelevant sub points, you dont check if the creation of the surface succeeded using surface_exists and you did not clear the surface of garbage with draw_clear_alpha...

have you tried setting the transparent color of your sprite to the same as the image's edge instead of black? or maybe disable interpolation when drawing, or possibly use a shader?

what is the desired result... I'm assuming with the CRT name in there you want a cathode ray display effect... you could get a crt shader off of the asset store... I'm sure someone made one..
 
B

basement ape

Guest
have you tried setting the transparent color of your sprite to the same as the image's edge instead of black? or maybe disable interpolation when drawing, or possibly use a shader?
That gave me an idea!
I tried to look into ways to set the transparent color of the sprite earlier but never found a way to do it. That's why I went with this whole method. But using a background color that's almost fully transparent seems to do the job just as well.

Thanks for the help!

what is the desired result... I'm assuming with the CRT name in there you want a cathode ray display effect... you could get a crt shader off of the asset store... I'm sure someone made one..
Yeh I'm already using the Old TV Filter by Vortex Game Studios. But CRT shader or no, whenever a sprite is scaled up using interpolation (trilinear filtering?) it'll introduce visible edges around them.
 
I

icuurd12b42

Guest
right hmm. set the canvas size to exactly the view in room size . I imagine you want low resolution for old tv display games like the nes or atari... like 240p or something like that? use surface_resize on the application surface... that will draw the images non scaled. and only scale the final draw of the application surface to the display (or window) doing interpolation with the final content... that should also work. less work for you. as long as you don't scale (up) sprites themselves, that should do the trick

in step of controller
if(surface_exists(appliaction_surface))
{
if(surface_get_width(application_surface)!=320)
{
surface_resize(application_surface,320,240);
}
}
 
I

icuurd12b42

Guest
Hey, try gpu_set_colorwriteenable(true,true,true,false) when drawing the sprite when crt mode is on.

if global.CRT_Mode == false
{
draw_sprite_ext(spr_forest_bigtree1_bg1, 0, bck_X, bck_Y, 1, 1, 0, c_white, 1);
}

else if global.CRT_Mode == true
{
gpu_set_colorwriteenable(true,true,true,false);
draw_sprite_ext(dyn_spr_forest_bigtree1_bg1_CRT, 0, bck_X, bck_Y, 0.5, 0.5, 0, c_white, 1);
}
 
B

basement ape

Guest
Thanks, I'll try both things out when I get back from work.
 
B

basement ape

Guest
I tried putting gpu_set_colorwriteenable(true,true,true,false); into the draw event and if I combine that with an almost transparent background color for the sprites the black seams around them go away completely! This is grand. Thanks so much for the help :)
 
Top