• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Draw a surface as big as a level room[SOLVED]

U

Unknown Yell

Guest
Hello there.
I'm making a Deadbolt clone to learn GML better.
I'm stuck on the light engine. Deadbolt lightning is really simple, I think it uses a surface or a shader to color the whole level black and then it "carves" a hole as big as the room the lamp is put in. With room I actually mean the room built in the room editor with objects, not the whole level.
Now, I need help on drawing the carved out surface, as I don't really know what to do, nor what to search on the internet.
 

c023-DeV

Member
Better have the lighting surface only at ViewPort Resolution (what you see). Then you could fill it black and paint white 'lights' on it and use multiply blendmode to paint that surface on the rest (at the current cameras position). It's a bit of translating the light coordinates to the relative position of the smaller surface and back but it saves a lot of memory compared to room sized surfaces (depending on how large the rooms are). (2048x2048 px is the default texture page size btw)
 
U

Unknown Yell

Guest
Thanks for the useful advice, I'll remember that, but it wasn't really my issue. My apologize, I wasn't really clear.
What I am trying to is this:
Light is contained in one room, and does not go trough the walls, but stops there.
I need help to get the boundaries of the room.
 
Considering the walls are objects, just scan from the light source out in two directions until collisions are found. If the light hits a wall, start a new scan downwards until it finds the floor. Then, make a primitive out of these two-to-four points and cut that shape out of the surface. You could even do it backwards to this by starting from where the light hits the ground or wall on either side and make primitives out of the shadows instead to fill in the surface.
 
U

Unknown Yell

Guest
Considering the walls are objects, just scan from the light source out in two directions until collisions are found. If the light hits a wall, start a new scan downwards until it finds the floor. Then, make a primitive out of these two-to-four points and cut that shape out of the surface. You could even do it backwards to this by starting from where the light hits the ground or wall on either side and make primitives out of the shadows instead to fill in the surface.
Thanks a lot, it worked.
I've used Yellow After Life's script, and this one by Zack Bell Games.
This is my code:
Obj_surf_vfx uses the Zack Bell script, wich creates the dark surface. Then, I get the room's boundaries with YAL script. It is used inside obj_light create event:
Code:
x0 = scr_collision_line_point(x,y,-room_width,y,obj_wall,false,true);
x1 = scr_collision_line_point(x,y,room_width,y,obj_wall,false,true);
y0 = scr_collision_line_point(x,y,x,-room_height,obj_wall,false,true);
y1 = scr_collision_line_point(x,y,x,room_height,obj_wall,false,true);
Then, inside the step event I actually draw the light, using my script scr_light:
Code:
//get the target object and the color;
var obj = argument[0];
var col = argument[1];
if (surface_exists(obj_surf_vfx.surf_light)) {
    surface_set_target(obj_surf_vfx.surf_light);

    // set blend mode to subtract
    draw_set_blend_mode(bm_subtract);
    draw_set_color(col);
  
    //draw the light rectangle
    with (obj)
        draw_rectangle(x0[1],x0[2],x1[1],y1[2],false)
    // Reset
    draw_set_blend_mode(bm_normal);
    draw_set_alpha(1);
    surface_reset_target();
} else {
   //check if the surface exists
    obj_surf_vfx.surf_light = surface_create(room_width, room_height);
    surface_set_target(obj_surf_vfx.surf_light);
    draw_clear_alpha(c_black, 0);
    surface_reset_target();
}
background_x[1] -= 0.5;
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
The way this is usually handled (if you've been around the GM forums sometime around 2008-2009, you might recall a big influx of games with lighting and/or destructive terrain systems) is by covering the room with more reasonably sized surfaces. Nowadays 1024x1024 will work pretty well. Then you figure out which surfaces overlap the thing that you're about to draw, and draw it to each of them with an offset. And draw the surfaces overlapping the view with a simple for-loop.

The other way would be to present your visibility data as non-pixel as such (e.g. marching squares), but it might be tricky to find a working example for this.
 
Top