GameMaker [SOLVED + FINAL CODE] When creating a surface... (lighting)

PlayerOne

Member
To make a long story short I followed the lighting tutorial by Talent Lost and I ran into a bit of stumbling block.



Everything works as intended but I use large rooms. Since I'm creating surfaces at the start of these rooms to make this lighting system to work by the room width and height the frame rate chugs to a crawl. In theory I thought of a way to do this and that is to create a surface "filter" of sorts on the gui layer. While I can draw surfaces it doesn't draw the lights I put in the room when doing this. I'm thinking I would have to update the surface in some way for that to happen.

Is there a method to updating the surface "filter" to ensure the lights do appear within camera range or do I have to draw the entire surface of the room in a single go? If the latter I'll have to scale back the rooms to compensate for this issue.

Any input is appreciated.
 

Attachments

Relic

Member
I'm guessing you are using views to only show a part of the room within your game window? Instead of drawing to the GUI layer (which you will regret if you need to use the GUI layer later), try drawing a surface just the size of the view, not the room. You will also need to determine where each light is in terms of surface coordinates.

Imagine your room is 2000x1000. Your view is 640x480 and your view top left corner is at 250,100 currently. A light starting at 250,100 in the room would be drawn at 0,0 on the surface. A light at 350,150 in the room would be drawn at 100,50 in the surface.... etc.
 

PlayerOne

Member
I'm guessing you are using views to only show a part of the room within your game window? Instead of drawing to the GUI layer (which you will regret if you need to use the GUI layer later), try drawing a surface just the size of the view, not the room. You will also need to determine where each light is in terms of surface coordinates.

Imagine your room is 2000x1000. Your view is 640x480 and your view top left corner is at 250,100 currently. A light starting at 250,100 in the room would be drawn at 0,0 on the surface. A light at 350,150 in the room would be drawn at 100,50 in the surface.... etc.
I get what your saying so far. However wouldn't the surface have to factor in the lights when being created at the start of the room in order to maintain the "shine" effect OR do I have to create separate surfaces for each of the lights in the game?
 

Relic

Member
Just watched the tutorial so I can get up to speed with what you are doing.

Psuedo code:

if surface does not exist, create it with view dimensions
set draw target to surface
clear surface to black
set blendmode to subtract
with objlight, draw light sprite at adjusted coordinates (doesn't matter if lights are outside of the surface, nothing will be drawn outside the surface)
set blendmode to normal (or do the colour technique with bm_zero if you want)
reset surface target
draw surface at view coordinates in room

If this is happening every draw step, your surface will keep updating. You don't have a static surface created at the start of the room - it is dynamic, updating each step. That's how the tutorial did it as well anyway, otherwise the flicker would not work.
 

PlayerOne

Member
Just watched the tutorial so I can get up to speed with what you are doing.

Psuedo code:

if surface does not exist, create it with view dimensions
set draw target to surface
clear surface to black
set blendmode to subtract
with objlight, draw light sprite at adjusted coordinates (doesn't matter if lights are outside of the surface, nothing will be drawn outside the surface)
set blendmode to normal (or do the colour technique with bm_zero if you want)
reset surface target
draw surface at view coordinates in room

If this is happening every draw step, your surface will keep updating. You don't have a static surface created at the start of the room - it is dynamic, updating each step. That's how the tutorial did it as well anyway, otherwise the flicker would not work.
After watching friendly cosmonaut video on shadows I now figured out my problem but for some reason the surface doesn't cover the entire camera view.

shadow_.png


In addition here is the code for the darkness to follow the player.

Code:
var lt = global.light
var view_x = camera_get_view_x(view_camera[0]);
var view_y = camera_get_view_y(view_camera[0]);



if (surface_exists(lt))
{
surface_set_target(lt)
draw_clear(c_black)
   
   if instance_exists(par_xlight)
   {
       with(par_xlight)
       {

       gpu_set_blendmode(bm_subtract)
       draw_sprite_ext(sprite_index,0,x-view_x,y-view_y,image_xscale+xradius,image_yscale,image_angle,-1,1)
       gpu_set_blendmode(bm_normal)       
       }
   

   
   }
   


       surface_reset_target()
       draw_surface_ext(lt,view_x,view_y,1,1,0,c_white,0.5)
}
else
{
global.light = surface_create(1140,640);   
}
 

PlayerOne

Member
Stupid me I got the wrong dimensions for the surface. Too many numbers to keep track within my game I can tell you that.

FINAL CODE:

CONTROLLER OBJECT:
Code:
//CREATE:
global.light=-1
Code:
//DRAW:
var lt = global.light
var view_x = camera_get_view_x(view_camera[0]);
var view_y = camera_get_view_y(view_camera[0]);
var viewport_w = camera_get_view_width(view_camera[0])
var viewport_h =camera_get_view_height(view_camera[0])


if (surface_exists(lt))
{
surface_set_target(lt)
draw_clear(c_black)
 
   if instance_exists(par_xlight)
   {
       with(par_xlight)
       {

       gpu_set_blendmode(bm_subtract)
       draw_sprite_ext(sprite_index,0,x-view_x,y-view_y,image_xscale+xradius,image_yscale,image_angle,-1,1)
       gpu_set_blendmode(bm_normal)     
       }
 

 
   }
       surface_reset_target()
       draw_surface_ext(lt,view_x,view_y,1,1,0,c_white,0.5)
}
else
{
global.light = surface_create(viewport_w,viewport_h); 
}

PARENT OBJECT: par_light

Code:
CREATE:
xradius=-1
Code:
STEP:
flicker_x = random_range(-0.01,+0.01);
xradius +=flicker_x;
xradius = clamp(xradius,0.06,0.9)
 
Top