• 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 Lighting help

V

Vanthex

Guest
HI guys,
This is my script that I use to determine how dark a block should be, here is the result:

However this only works along the Y axis, where basically the light is only casted downwards, so if I go straight down I would end up like this:

The blocks on the sides are not lit up.
So I want the light source to be able to affect blocks that are next to each other, this is my code and I don't know how to incorporate that into it. (I'm new to coding)
Code:
var a = 0;

for (var i = 1; i <= 4; i++) {
    if (place_meeting(x, y - (sprite_height * i), obj_tile)) {
        a += 1;
    }
}

if (a > 0) {
    a = (a * 25) / 100;
}

return a;
This just returns an alpha value for how dark it is going to draw the block.
 
Q

Quackertree

Guest
You'd probably have to do something iterative with this. You should create a ds_grid which holds a value between {0, 1}, indicating how dark the block should be (with 0 being dark and 1 being light). Whenever something in the world updates, you'd have to recalculate the ds_grid, something along the following lines:

- Start at the block which has recently changed
- Count how many blocks are around it and divide this value by the total amount of blocks possible, and invert that value
Ex.: If there are 5 blocks around the block, than that position in your ds_grid lightmap should equal: (1 - 5/8)
- Repeat the above step for several blocks around the starting block
- Keep repeating until you've calculated for about 10 blocks in a radius around the starting block

It's kinda complex for a beginner, but this would be a way to do it.
 
V

Vanthex

Guest
Hi THanks for the reply
You'd probably have to do something iterative with this. You should create a ds_grid which holds a value between {0, 1}, indicating how dark the block should be (with 0 being dark and 1 being light). Whenever something in the world updates, you'd have to recalculate the ds_grid, something along the following lines:

- Start at the block which has recently changed
- Count how many blocks are around it and divide this value by the total amount of blocks possible, and invert that value
Ex.: If there are 5 blocks around the block, than that position in your ds_grid lightmap should equal: (1 - 5/8)
- Repeat the above step for several blocks around the starting block
- Keep repeating until you've calculated for about 10 blocks in a radius around the starting block

It's kinda complex for a beginner, but this would be a way to do it.
This is my code and it's not working: nothing is showing up
Code:
///Lighting grid
global.lightinggrid = ds_grid_create(160,128);
//Fills all cells with full brightness, which is 1
ds_grid_set_region(global.lightinggrid,0,0,159,127,1);
//Reads worldgrid, if there's a block, place 0.75 (darker)
global.LightX = 0
global.LightY = 0
repeat (160){
repeat (127){
//Current cell of the lighting grid
global.LightFill = ds_grid_get(global.lightinggrid,global.LightX,global.LightY)
//Current cell of the world grid, to test if there is a block or not
global.LightRead = ds_grid_get(global.worldgrid,global.LightX,global.LightY)
//If there is a block and the current lighting is full brightness (1), then set it to 0.75 (darker)
if (global.LightRead != 0 && global.LightFill = 1) {ds_grid_set(global.lightinggrid,global.LightX,global.LightY,0.75)}
//The lighting value above the current block
global.LightAbove = ds_grid_get(global.lightinggrid,global.LightX,global.LightY-1)
//If the block and the block above it have the same brightness, the block has to have a darker value
if (global.LightFill = 0.75 && global.LightAbove = 0.75) {ds_grid_set(global.lightinggrid,global.LightX,global.LightY,0.5)}
if (global.LightFill = 0.5 && global.LightAbove = 0.5) {ds_grid_set(global.lightinggrid,global.LightX,global.LightY,0.25)}
if (global.LightFill = 0.25 && global.LightAbove = 0.25) {ds_grid_set(global.lightinggrid,global.LightX,global.LightY,0)}
if (global.LightFill = 0 && global.LightAbove = 0) {ds_grid_set(global.lightinggrid,global.LightX,global.LightY,0)}
global.LightY += 1
}
global.LightX += 1
global.LightY = 0
}
//Sets alpha value
alpha = ds_grid_get(global.lightinggrid,x/32,y/32)

//Draw self
draw_self();

//Draw darkness
draw_sprite_ext(sprite_index, image_index, x, y, 1, 1, 0, c_black, alpha);
 
Q

Quackertree

Guest
Nothing is showing up, because you're not reading the darkness from the ds_grid. You should start with that:

Code:
var v = 1;
var xx, yy;

xx = floor(x / sprite_width);
yy = floor(y / sprite_height);

if(!is_undefined(global.lightinggrid[# xx, yy]))
{
v = global.lightinggrid[# xx, yy];
//Optional interpolation and other jazz here
}else{show_debug_message("This block doesn't exist in the grid! ("+string(xx)+","+string(yy)+")");}

draw_sprite_ext(sprite_index, image_index, x, y, 1, 1, 0, merge_colour(c_black, c_white, v), alpha);
Sidenote: The syntax grid[# x, y] is equal to ds_grid_get(grid, x, y). Also not sure if merge_colour(...) is the correct name, but it should be something along those lines. :)

Give that a try and let me know if it worked. I just wrote this from the top of my head so I cannot guarantee anything here.

P.S.: Sorry for the late response; Haven't had internet connection in a while! :/
 
B

bojack29

Guest
Yup. Use a grid.

To determine the alpha of each square you can simply do as you did before but with grids. Will save you lots of time and resources. Basically you should only need to hit all the blocks within view. No point in checking ALL blocks when you destroy one of them.

Use a surface to draw varying levels alphas of dark squares over each block to display light. When a square is covered by each block the alpha block drawn over it should be darker, but you'll also have to account for the y axis too. Even if the square is covered all around, deeper squares will have to naturally have a darker alpha, so you'll have to account for that.

Something like this should work.
Code:
var a, b, c, d, x0, y0, x1, y1;

x0 = view_xview[0] div cellSize;
y0 = view_yview[0] div cellSize;
x1 = view_wview[0] div cellSize;
y1 = view_hview[0] div cellSize;

surface_set_target(surfaceLightMap);
for(a = x0;a <= x1;a ++){
     for(b = y0;b <= y1;b ++){
          d = 0;
          for(c = 0;c <= 3;c ++){
               d += sign(lightmap[# a, b]) * .125;
          }
          d += y0 / 100;//You'll need to change this value to provide different spectrums of darkness to the surface block
          draw_rectangle_colour(x0 * cellSize, y0 * cellSize, x0 * cellSize + cellSize, y0 * cellSize + cellSize, c_black, c_black, c_black, c_black, d);
     }
}
surface_reset_target(surfaceLightMap);
Basically what this code attempts to do is provide the alpha of the block based on two set of criteria. Half the alpha is represented by the y axis by which it is located on the grid. Further down cells will approach a number closer to .5. Then I evaluate all blocks around it to determine the rest of the alpha. Each block around it represents an extra alpha of .125, which multiplied by 4 (or completely surrounded) means an additional alpha of .5.
 
Last edited by a moderator:
B

bojack29

Guest
Honestly based on the image you've shown you can basically just add up squares that are directly ontop of each square.

So a square with 4 squares on top will have an alpha of 1. A square with 3 on top will have an alpha of .75 etc.
Code:
var a, b, c, d, x0, y0, x1, y1;

x0 = view_xview[0] div cellSize;
y0 = view_yview[0] div cellSize;
x1 = view_wview[0] div cellSize;
y1 = view_hview[0] div cellSize;

surface_set_target(surfaceLightMap);
draw_set_blend_mode(bm_subtract);
draw_rectangle(view_xview[0], view_yview[0], view_xview[0] + view_wview[0], view_yview[0] + view_hview[0], true);
draw_set_blend_mode(bm_normal);
for(a = x0;a <= x1;a ++){
     for(b = y0;b <= y1;b ++){
          d = 0;
          for(c = 0;c <= 3;c ++){
               d += sign(lightmap[# a, b - c]) * .25;
          }
          draw_rectangle_colour(x0 * cellSize, y0 * cellSize, x0 * cellSize + cellSize, y0 * cellSize + cellSize, c_black, c_black, c_black, c_black, d);
     }
}
surface_reset_target(surfaceLightMap);
The grid simply determines if a block is in a location. 1 for block, 0 for no block.
 
Last edited by a moderator:
Top