Asset - Scripts Fast Lights

slojanko

Member
I'm surprised how well this runs. Better than the shader based lights, I've never had a good experience with shaders in GMS.
 
N

nigmatech

Guest
Also another question - when I use your day-night cycle (which works excellent, thank you very much) during the day I get overly bright colors of everything, is there any way to gradually lower alpha together with the raising color?
 
N

nigmatech

Guest
I'm surprised how well this runs. Better than the shader based lights, I've never had a good experience with shaders in GMS.
This system does use shaders, or did you mean some completely different approach?
 

Buff

Member
Hello...

I feel kinda stupid for asking this but i need to know..

I really love this asset and stuff... and i have been trying to get the lighting to follow my character in my game. Guess you can imagine what im talking about.
I been trying for hours know without luck. I feel like a dumb **** for not know how to code it. hope i could get a little help here?
Hey Oliver,

Don't get too frustrated, it takes time to learn something new.
Try creating a light in the create event of your character. The light will be drawn at the same x,y location as the character.

Alternatively if you want the light to not be at the same location but to move relative to your character, create a separate object that will be your light. Create the light with light_create in the create event of that object, the light will be drawn at the x,y location of that object. Now in the step event of your light object set the x value and y value to character.x and character.y, possibly transformed with some offset.

Check out the light_mouse object in the example, this light always follows the mouse.

Buff
 

Buff

Member
I have a problem with shader, that in the android compilation works without any problem on two devices, which have completely different resolutions but for some reason shader flickers and loses objects on the third device Asus Zenfone Go.

Shows alternately either tilesets or draws objects never together, sometimes it goes normally but flickers again after a while.
Hello Nedenir,

That's quite interesting. I don't know if it is a related to Fast Lights though.
It sounds like it could be a depth issue, I think some devices treat objects that have the same depth differently. When two objects that are on top of each other have the same depth, it is ambiguous as to what object goes on top.
Try making sure the depth values for every object are different.

Buff
 

Buff

Member
Excellent script. Are you planning on adapting it to GMS 2?

Also a question - is there a way to get object status (is it in light or not)?
Hey nigmatech,

I haven't started using GMS 2 yet but probably will eventually. Hopefully it won't be too difficult, gnemnji has already done it.
Hmm, there isn't exactly a way to tell if an object is in a light or not. On line 44 in the light_draw script this bit check is used:
Code:
var _light_inside = rectangle_in_rectangle(_light_left, _light_top, _light_right, _light_bottom, argument0, argument1, argument0 + global._light_width, argument1 + global._light_height) > 0
You could copy that value to the light object and use it later but it's a pretty basic check. It won't tell you if the object is in a shadow or not, just if it is close enough to a light.

Also another question - when I use your day-night cycle (which works excellent, thank you very much) during the day I get overly bright colors of everything, is there any way to gradually lower alpha together with the raising color?
This is actually how bright the world is, with the shadow overlay gone. The best way to control how dark the shadow overlay is with the color value set with light_set_ambient_color. If you want to keep it dark, set this to a dark color.

Buff
 

Buff

Member
Absolutely love this extension! I don't have a gigantic amount of the GML, but I've been able to do dynamic shadows and updates and all the good stuff fairly easily. I am curious, and lost, on how to create lighting only on the surface of my world. I'm making a game similar to Terraria and want the surface of the world to be lit up with everything below it being blacked out. Could you help me in anyway in doing this? I can email you or dropbox the project file to you and you can take a closer look at it if you'd like, thank you!
Hi SmokinLettuce,

I don't think the lighting engine will help on that front. It already makes things darker the farther away they are from a light. You could set the ambient color to full black and have the shadows cover everything that is under them.

I believe the way Terraria does it is by making each block darker as they get farther from the surface. You can use draw_sprite_color on your blocks with a darker and darker color each time the farther the blocks are from the surface. You can check which block is a surface block just by seeing if there is one above it. If there is then you color the block black.

Buff
 

Witzler

Member
That's some fine work you did there Buff! And even free! You are insane :D
I wanted to ask if there is a possible way to check shadows for collision/ make them solid, because I can't find a way to make a drawn thing to a collision mask/ point perfect collision..
Would be cool if you had an idea and thanks in advance!

Witzler
 
M

My_name_is_username

Guest
Hello, Buff! Agree with others, its a wonderful lighting/shadowing system. And it looks fantastic! Well... In your demo at least.
Now to the point. I am trying to make a flashlight for the player and am trying to figure out how lights work (I'm a newbie) and managed to figure out by now how to attach light source to the player, but... When I try to make light follow the mouse, it just doesn't work how I want it to.
Game starts, light is being created (pointing from the player (source of light) to the mouse' onscreen position) and then freezes in this position.
I want to allow player to use flashlight freely in any direction with "mouse_x" and "mouse_y" so that "x1" and "y1" are the player's position (light source) and "x2" and "y2" are position of the mouse pointer (to where light is pointing). I hope you understand what I mean. And yes, I looked through your example project. And no, still can't understand how it works. "Light Angle" value doesn't really help me much.
Thanks in advance!
EDIT: OK, it seems like the light rotation parameters are kept somewhere in the "light_draw" script. Apparently in the "draw lights" section, because changing script "light_set_rotation" doesn't give me much. Well, actually it gives nothing. LoL. I tried to replace "= argument0" to "= point_direction(x,y,mouse_x,mouse_y). Damn. I guess the original creator of the script will help me (and others as well) to better read the code. Any help?
 
Last edited by a moderator:

Buff

Member
Hello, Buff! Agree with others, its a wonderful lighting/shadowing system. And it looks fantastic! Well... In your demo at least.
Now to the point. I am trying to make a flashlight for the player and am trying to figure out how lights work (I'm a newbie) and managed to figure out by now how to attach light source to the player, but... When I try to make light follow the mouse, it just doesn't work how I want it to.
Game starts, light is being created (pointing from the player (source of light) to the mouse' onscreen position) and then freezes in this position.
I want to allow player to use flashlight freely in any direction with "mouse_x" and "mouse_y" so that "x1" and "y1" are the player's position (light source) and "x2" and "y2" are position of the mouse pointer (to where light is pointing). I hope you understand what I mean. And yes, I looked through your example project. And no, still can't understand how it works. "Light Angle" value doesn't really help me much.
Thanks in advance!
EDIT: OK, it seems like the light rotation parameters are kept somewhere in the "light_draw" script. Apparently in the "draw lights" section, because changing script "light_set_rotation" doesn't give me much. Well, actually it gives nothing. LoL. I tried to replace "= argument0" to "= point_direction(x,y,mouse_x,mouse_y). Damn. I guess the original creator of the script will help me (and others as well) to better read the code. Any help?
Hey username,
You almost have the right idea but you're not using GM scripts correctly. The script, light_set_rotation, has to be called in an object event in order to work. In the step event of your light object put:
Code:
light_set_rotation(point_direction(x, y, mouse_x, mouse_y))
This will update the rotation of the light every step.

Be sure to check out the example and the documentation on the first post which describes how to use the scripts.
 
Last edited:
M

My_name_is_username

Guest
Hey username,
You almost have the right idea but you're not using GM scripts correctly. The script, light_set_rotation, has to be called in an object event in order to work. In the step event of your light object put:
Code:
light_set_rotation(point_direction(x, y, mouse_x, mouse_y)
This will update the rotation of the light every step.

Be sure to check out the example and the documentation on the first post which describes how to use the scripts.
Hah! I think my mind got blurred back then. I did everything exactly like you said BUT I was doing it in the "begin step" lol. That's why nothing worked for me. Thank you for your help, man! It's a really helpful advice!
 
G

Gyoza_sauce

Guest
Edit: Never mind! I got it!

But I need to say that this is light engine is amazing! Thank you for making it, and I can't thank you enough for making it accessible for free!
 
Last edited by a moderator:
G

Gyoza_sauce

Guest
I've been playing around with this system for a while now, and as I said above, it's amazing. However, I have one question. Why are the primary colours red, green, and blue? And not red, yellow, and blue? Wouldn't it make more sense to have yellow instead of green? As you can easily get any colour from these three? yellow + blue = green.

Edit: Okej, after looking around in other places r, g, b seems like some kind of standard. No need for an answer.
 
Last edited by a moderator:

Buff

Member
I've been playing around with this system for a while now, and as I said above, it's amazing. However, I have one question. Why are the primary colours red, green, and blue? And not red, yellow, and blue? Wouldn't it make more sense to have yellow instead of green? As you can easily get any colour from these three? yellow + blue = green.

Edit: Okej, after looking around in other places r, g, b seems like some kind of standard. No need for an answer.
Hello,

I'm glad you're enjoying Fast Lights!
RGB is a pretty standard color model, but GameMaker supports two color types out of the box, RGB and HSV (Hue, Saturation, and Value). You can use make_colour_hsv if you prefer.
 
I'm trying to get this asset to work in GMS2 but it is constantly complaining that global._lights and global._light_casters is not defined. Although I've checked and can see that they are set up in the main_objects instance - which I added to the test_room.

After importing the demo project into GMS2 I reorganised the Layers so that the controller (main_objects) was on a layer on its own. The Lights were on a layer called 'Lights' and likewise moved all the casters to their own layer.

Is it possible to use this asset in GMS2?
 
N

nigmatech

Guest
I'm trying to get this asset to work in GMS2 but it is constantly complaining that global._lights and global._light_casters is not defined. Although I've checked and can see that they are set up in the main_objects instance - which I added to the test_room.

After importing the demo project into GMS2 I reorganised the Layers so that the controller (main_objects) was on a layer on its own. The Lights were on a layer called 'Lights' and likewise moved all the casters to their own layer.

Is it possible to use this asset in GMS2?
Yes, I am currently using this script with GMS 2. I have implemented it quite a long time ago, but I seem to recall that it did not take any significant tinkering. Try to import it in its entirety in GMS 2 as a new project and go from there
 
That's exactly what I did do. I just imported the project as new and attempted to run it. It immediately started complaining about global._light_casters being used before being set.

I tried a few things to get it working but nothing worked.
 
I've worked it out. The GameController object that performs the initial light_init() function must be the first instance on the layer that contains all the casters and lights, otherwise it will fail.
 
  • Like
Reactions: JAG
D

Donkey Kongus

Guest
Hey, I'm working on a project using Fastlights, and so far it's very good. I am having an issue, though, and was wondering if you knew of any way to fix it. Whenever the camera or view moves, there's a noticeable delay before the lighting catches up to the new view angle. I'm just sorta looking to remove that effect. If you know any way of patching it out, I'd really like to know. I've been trying to do it on my own for a bit now, but due to general inexperience on my end, I haven't really gotten anywhere.
 

Seryal

Member
I'm happy that I found this. I was able to create the shadow map, create the light around my player object and turn my wall blocks into casters; but the wall blocks do not cast.
I had my own lighting system that I removed because I thought it was interfering but it still does not create shadows for the wall blocks.

I've looked at the example project and my coding for the block caster is identical except for the physics, which I doubt make a difference since it's just a stationary block.
I'm initializing with
Code:
light_init(room_width, room_height, 256, c_black, 0.5, room_speed);
I'm creating light around my player with
Code:
light_create(sp_light_point, 1, c_white, 1, 0, false);
And in my block object's creation code I have
Code:
light_create_caster();
And I'm using the destroy for the lights and casters as well.

Any ideas what I might be doing wrong or need to change/add?
 

Buff

Member
I'm happy that I found this. I was able to create the shadow map, create the light around my player object and turn my wall blocks into casters; but the wall blocks do not cast.
I had my own lighting system that I removed because I thought it was interfering but it still does not create shadows for the wall blocks.

I've looked at the example project and my coding for the block caster is identical except for the physics, which I doubt make a difference since it's just a stationary block.
I'm initializing with
Code:
light_init(room_width, room_height, 256, c_black, 0.5, room_speed);
I'm creating light around my player with
Code:
light_create(sp_light_point, 1, c_white, 1, 0, false);
And in my block object's creation code I have
Code:
light_create_caster();
And I'm using the destroy for the lights and casters as well.

Any ideas what I might be doing wrong or need to change/add?
Hello Seryal,

Are you calling light_draw() in the draw event of your main object?
 

Buff

Member
Hey, I'm working on a project using Fastlights, and so far it's very good. I am having an issue, though, and was wondering if you knew of any way to fix it. Whenever the camera or view moves, there's a noticeable delay before the lighting catches up to the new view angle. I'm just sorta looking to remove that effect. If you know any way of patching it out, I'd really like to know. I've been trying to do it on my own for a bit now, but due to general inexperience on my end, I haven't really gotten anywhere.
Hey,

What is your update iterations in light_init? You might be seeing that if your iterations are too small. Try setting it to room_speed.
 

Buff

Member
That's some fine work you did there Buff! And even free! You are insane :D
I wanted to ask if there is a possible way to check shadows for collision/ make them solid, because I can't find a way to make a drawn thing to a collision mask/ point perfect collision..
Would be cool if you had an idea and thanks in advance!

Witzler
This would be challenging, but I have seen games use surfaces for collisions. In theory you could you could save the shadow surface as a sprite and collide with the black parts because the rest is transparent. I don't know how to do this off the top of my head, but there are lots of games that have "destroyable terrain" that is drawn by a surface.
 

Seryal

Member
Hello Seryal,

Are you calling light_draw() in the draw event of your main object?
Yes I was, I think it was a depth issue between certain objects. I got someone else to help me and now it's working, thank you!
 
D

Donkey Kongus

Guest
Hey,

What is your update iterations in light_init? You might be seeing that if your iterations are too small. Try setting it to room_speed.
Unfortunately that didn't really do anything. I already have both the room speed and the iterations set to 120. Just to clarify a bit, it's not a constant stuttering, just whenever the camera moves. It's also slightly noticeable in the example project.
 

Seryal

Member
Unfortunately that didn't really do anything. I already have both the room speed and the iterations set to 120. Just to clarify a bit, it's not a constant stuttering, just whenever the camera moves. It's also slightly noticeable in the example project.
Same here for when I got it working. It's not a huge problem for me but if there's a fix for that that'd be great to know about!
 
D

Donkey Kongus

Guest
I got a quick cropped screencap of the example gmx doing it. Seconded what Seryal said, it's not a huge problem, but a fix would be really appreciated. Really looking forward to a fix though
 

Attachments

Last edited by a moderator:

Buff

Member
Unfortunately that didn't really do anything. I already have both the room speed and the iterations set to 120. Just to clarify a bit, it's not a constant stuttering, just whenever the camera moves. It's also slightly noticeable in the example project.
Hmm, I've only seen the stuttering you describe when running with a low iteration rate.
Try setting the iterations to -1, this will force it to redraw every frame.
 
D

Donkey Kongus

Guest
Hmmm. Odd. This does fix the issue in the example gmx, but not the one I'm using. I should also state that I am using only a slightly edited version of the gmx's files, just with physics and some time of day stuff removed. I'm gonna keep rooting around and see if it's something on my end, but I'm not really sure what it could be. Like I said, it's mainly just an import of stuff from the example. But damn does the lighting in the gmx look smooth now that its fixed. If you had any advice or ideas here I'd really appreciate it though.
 
Last edited by a moderator:

Buff

Member
If you start with a blank project and add the lighting system in do you still have the problem? Do you have a version of the project you can upload so I can investigate?
 
D

Donkey Kongus

Guest
Sorry for the late response! I was rooting around, and it turns out it was something on my end actually. Couple of things were conflicting. I can provide a bit more detailed reasoning @Seryal is still having issues, but it was really nothing interesting.
 

Seryal

Member
Sorry for the late response! I was rooting around, and it turns out it was something on my end actually. Couple of things were conflicting. I can provide a bit more detailed reasoning @Seryal is still having issues, but it was really nothing interesting.
Yes, I'm curious. What changes did you have to make to stop the lights from shaking when the camera moves?

@Buff I tried setting the iterations to -1, but that just made the entire game black screen with a lot of failed popups before it would even load.


EDIT: Nevermind I think I solved it!
 
Last edited:
W

wroberts1014

Guest
Edit: Solved the issue
 
Last edited by a moderator:
This wonderful asset assumes that the entire room or view is in a state of perpetual light or darkness.
Is there a way to render the darkness only to a select area?
For example: day time outdoors in the hills; there stands a house upon which we enter, to find it dark inside. (the darkness must stop at the walls, not continuing outside into the day light)

Also, as it is, (circumstances depending) lights still shine through walls.
 
Last edited:
Is there a way to adjust the x/y offsets of light_create without adjusting the offset of the sprite? I have a streetlight object as the light source but it appears from the base (since that's where the offset is).
It has to be created from the streetlight object otherwise placing/removing the streetlight in game would be buggy.
 

Buff

Member
Is there a way to adjust the x/y offsets of light_create without adjusting the offset of the sprite? I have a streetlight object as the light source but it appears from the base (since that's where the offset is).
It has to be created from the streetlight object otherwise placing/removing the streetlight in game would be buggy.
I had a similar problem. My solution was to create a separate object to just be the light and then always draw it at the offset location of the lamp. This isn't too bad if you create the light in the lamp's create event:
Code:
xoffset = 0
yoffset = 16
light = instance_create(x + xoffset, y + yoffset, Light)
Then in the end step event you move the light with your lamp, if it needs to move:
Code:
with light {
    x = other.x + other.xoffset
    y = other.y + other.yoffset
}
Just make sure to remember to destroy your light in the lamp's destroy event:
Code:
with light {
    instance_destroy()
}
This way you only have to create the lamp object and the light instance will be automatic. With this setup you can even make the lamp itself a caster, which can look pretty neat.
 
Would this work with several instances of the streetlight object without interfering with eachother's lighting? Is that what the light variable does?

And thanks for the help by the way. Really appreciate it!
 

Buff

Member
Would this work with several instances of the streetlight object without interfering with eachother's lighting? Is that what the light variable does?

And thanks for the help by the way. Really appreciate it!
Yeah. What instance_create does is creates an "instance" of an object, which is essentially a copy of an object , that can be acted upon independently from other instances. Using instance_create is equivalent to placing an object in the room editor, this is just how you do it with code.

instance_create also returns the "instance id" of the instance it created, here we store the id in the light variable. The id acts as a handle that allows us to get and set variables on the specific instance attached to it.
 

JeffJ

Member
This wonderful asset assumes that the entire room or view is in a state of perpetual light or darkness.
Is there a way to render the darkness only to a select area?
For example: day time outdoors in the hills; there stands a house upon which we enter, to find it dark inside. (the darkness must stop at the walls, not continuing outside into the day light)

Also, as it is, (circumstances depending) lights still shine through walls.
I would like to know this as well.
 
D

Donkey Kongus

Guest
Hey, I'm back again. This time I'd like to know if there's a way to create a caster that takes the sprites transparency into consideration. Right now, I have a door object with a sprite that has animation to open it, and I'd really like for just the non-transparent part to block light as the door opens. I'm not quite sure if that makes any sense, but I'd really appreciate it if anyone knew a way to do something like that.
 

Buff

Member
Hey, I'm back again. This time I'd like to know if there's a way to create a caster that takes the sprites transparency into consideration. Right now, I have a door object with a sprite that has animation to open it, and I'd really like for just the non-transparent part to block light as the door opens. I'm not quite sure if that makes any sense, but I'd really appreciate it if anyone knew a way to do something like that.
Hmm, the shadow casters are based on a set of points, not the content of the sprite. You'd have to create a caster from a set of points and then change those points with the animation. There's no way to do that with the system right now, but it's not impossible. Alternatively if the animation is just a rotation or a translation, the caster points will move with the object based on the x, y location and image_angle. You could change your animation to be procedural instead of baked into a animated pixels or you could create a dummy caster object that mimics your existing animation.
 

Nephalen

Member
Hello Buff.
I'm sorry for reviving such an old thread but I really love your light system but I am having trouble understanding a specific part of the code.
In the script called "Light_draw" you say that I can change X,Y to change the location to draw the shadowmap. I have tried switching around the code some but I'm not getting any real results.

What I am after is to have (for example) only the bottom half of the screen using the light and shadow system while the top part works normally. I want to make it like a cave but I am having no luck. If you have the time I'd love to know what exactly to change to achieve this effect.
 

Buff

Member
Hello Buff.
I'm sorry for reviving such an old thread but I really love your light system but I am having trouble understanding a specific part of the code.
In the script called "Light_draw" you say that I can change X,Y to change the location to draw the shadowmap. I have tried switching around the code some but I'm not getting any real results.

What I am after is to have (for example) only the bottom half of the screen using the light and shadow system while the top part works normally. I want to make it like a cave but I am having no luck. If you have the time I'd love to know what exactly to change to achieve this effect.
Hey Nephalen,

Yes this is possible. You specify the size of the shadowmap with light_init and the where to draw it with light_draw.
In the included example, the map is the size of the view and is always drawn where the view is in the room, if instead you change it to be drawn at a specific location, it will stay there.

I was able to draw the shadowmap as a small square in the middle of the room with the example:


by changing map to have a size of 500x500 and drawing it at (512, 512).

In the create event of main, try changing light_init to
Code:
light_init(500, 500, 1024, color, 0.35, -1)
and in the draw event change light_draw to
Code:
light_draw(512, 512, true, true, blur)
You can simply make the shadowmap as large as your cave and draw it where the cave should be.
 

Buff

Member
i didn't understand the point caster so, have some way to make an real-time shadow of a animated player?
Hello Killuado,
This is possible, although a bit tricky and tedious. My recommendation would be to make a general shape around your character instead of trying to animate it.
Nonetheless, I will explain how to animate shadows.

The trick is creating a new list of points for each frame of the animation. I would create a list of list to store the frames, and then create each frame as a list of points:

Code:
// Create two lists of lists for storing points.
pointsx = ds_list_create();
pointsy = ds_list_create();

// Create each frame as a list of points.
// Frame zero...
var pointsx_frame = ds_list_create();
var pointsy_frame = ds_list_create();

ds_list_add(pointsx_frame, 0);
ds_list_add(pointsy_frame, 0);

ds_list_add(pointsx_frame, 128);
ds_list_add(pointsy_frame, 0);

ds_list_add(pointsx_frame, 128);
ds_list_add(pointsy_frame, 128);

ds_list_add(pointsx_frame, 0);
ds_list_add(pointsy_frame, 128);

// Add the frame to the list.
ds_list_add(pointsx, pointsx_frame);
ds_list_add(pointsy, pointsy_frame);
And then create a caster from the first frame using a modified version of light_create_caster_from_points, the key is not to destroy the lists since we will need them later:
Code:
// Now create the caster from the first frame.
var first_frame_x = ds_list_find_value(pointsx, 0);
var first_frame_y = ds_list_find_value(pointsy, 0);

for (var i = 0; i < ds_list_size(first_frame_x); i++)
{
    _light_points_x[i] = ds_list_find_value(first_frame_x, i);
    _light_points_y[i] = ds_list_find_value(first_frame_y, i);
}

ds_list_add(global._light_casters, id);
You could do this in a similar way to light_create_caster_from_path as well.

Then in the step event you change which lists to use as the shadow array based on the image index:
Code:
// The image_index and the point frame index are the same.
// Get the current point frame from the list.
var current_frame_x = ds_list_find_value(pointsx, image_index);
var current_frame_y = ds_list_find_value(pointsy, image_index);

// Clear out the existing points since there may be more than this frame has.
_light_points_x = 0;
_light_points_y = 0;

// Set the caster points to the new points list.
for (var i = 0; i < ds_list_size(current_frame_x); i++)
{
    _light_points_x[i] = ds_list_find_value(current_frame_x, i);
    _light_points_y[i] = ds_list_find_value(current_frame_y, i);
}
Again, you could use paths instead.

I have made a working example that has even more detail in the comments. Check out the "animated_caster" object to see this in action.
 

Buff

Member
I am happy to announce the release of Fast Lights 2 which adds support for GMS2 and a number of other features including multiple lighting systems, masked lightmaps, and a caster creator tool. Check it out here.
 
Top