This is just a tech demo of using a hex grid to display lighting effects suitable for small games. This is the perfect example of very simple of fog of war.
It features the ability to turn on a penumbra, this is the effect you get from having the light source as an area rather than coming from a single infinitely small point. It creates a graduation between the light and dark area.
Just the mouse
Clicking the green button allows you to turn on a penumbra.
I found that if you use GameMaker and you have WebGL set to disabled you can’t use draw_primitive at all and if you have WebGL enabled draw_primitive performs exceedingly poorly, because of this I fell back to drawing an image of a hexagon and using that. I don’t know if other have a solution to this but it wasn’t worth my time to investigate it any further as the performance is satisfactory however from a programming point of view this irks me
I would love to find an elegant solution to stop the penumbra from coming through the walls.
I would like to cache the results so you don’t need to do the collision detection, however the collision detection seems to perform better than the caching, I think this is because it actually moves large amounts of data around when updating the arrays so I just stuck with crunching the collision detection on every frame.
When the system loads I have to stagger the creation of the hex grid, not for performance reasons but because I get each tile to create the tiles that surround it and the computer thinks my program has gone recursive and errors. So to prevent this I put a 2 frame gap between the creation of the tile and when it spawns the ones around it.
gridaamount = 6 //6 and 4 tessellate but you can use grids that dont tessellate createangle = 360/gridaamount; diameter = 15; //15 distancetosee = 300; distanceoverwalls = diameter; // how far past the walls can it go? // Save the points that make up this hex pointsx[gridaamount-1] = ''; pointsy[gridaamount-1] = ''; for (i = 0; i < gridaamount; i ++) { pointsx[i] = x + lengthdir_x(diameter-4, createangle*i) pointsy[i] = y + lengthdir_y(diameter-4, createangle*i) }Draw Event:
draw_primitive_begin(pr_trianglelist); repeat(gridaamount) { draw_vertex(x,y) draw_vertex(pointsx[i], pointsy[i]); if (i+1 >= gridaamount) {ti=0} else {ti=i+1} draw_vertex(pointsx[ti], pointsy[ti]); i++ } draw_primitive_end();Step Event:
var dist = distance_to_point(mouse_x,mouse_y) var checkdis = diameter if (dist > distancetosee) { visible = true } else { if (collision_line(x+checkdis,y+checkdis,mouse_x,mouse_y,obj_wall,0,1) and collision_line(x-checkdis,y-checkdis,mouse_x,mouse_y,obj_wall,0,1) and collision_line(x-checkdis,y+checkdis,mouse_x,mouse_y,obj_wall,0,1) and collision_line(x+checkdis,y-checkdis,mouse_x,mouse_y,obj_wall,0,1)) { visible = true } else { visible = false } }Step Event With Penumbra:
if (obj_global.penumbra > 0) { // Casts penumbra shadows with transparency if (dist > distancetosee) { transparency = 1 } else { transparency = 0 if (collision_line(x+obj_global.penumbra,y+obj_global.penumbra,mouse_x,mouse_y,obj_wall,0,1)) {transparency += 0.25} if (collision_line(x-obj_global.penumbra,y-obj_global.penumbra,mouse_x,mouse_y,obj_wall,0,1)) {transparency += 0.25} if (collision_line(x-obj_global.penumbra,y+obj_global.penumbra,mouse_x,mouse_y,obj_wall,0,1)) {transparency += 0.25} if (collision_line(x+obj_global.penumbra,y-obj_global.penumbra,mouse_x,mouse_y,obj_wall,0,1)) {transparency += 0.25} } } else { // Simple collisions with on/off transparency if (dist > distancetosee) { transparency = 1 } else { transparency = 0 if (collision_line(x+checkdis,y+checkdis,mouse_x,mouse_y,obj_wall,0,1) and collision_line(x-checkdis,y-checkdis,mouse_x,mouse_y,obj_wall,0,1) and collision_line(x-checkdis,y+checkdis,mouse_x,mouse_y,obj_wall,0,1) and collision_line(x+checkdis,y-checkdis,mouse_x,mouse_y,obj_wall,0,1)) { transparency = 1 } } }