Asset - Scripts Fast Lights

Discussion in 'Marketplace' started by Buff, Nov 14, 2016.

  1. slojanko

    slojanko Member

    Joined:
    Jun 20, 2016
    Posts:
    113
    I'm surprised how well this runs. Better than the shader based lights, I've never had a good experience with shaders in GMS.
     
    Buff likes this.
  2. nigmatech

    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?
     
  3. nigmatech

    nigmatech Guest

    This system does use shaders, or did you mean some completely different approach?
     
  4. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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
     
  5. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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
     
  6. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.

    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
     
    Witzler likes this.
  7. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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
     
  8. Witzler

    Witzler Member

    Joined:
    Oct 7, 2017
    Posts:
    7
    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
     
    Buff likes this.
  9. My_name_is_username

    My_name_is_username Member

    Joined:
    Oct 19, 2017
    Posts:
    2
    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: Oct 19, 2017
  10. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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: Oct 23, 2017
    My_name_is_username likes this.
  11. My_name_is_username

    My_name_is_username Member

    Joined:
    Oct 19, 2017
    Posts:
    2
    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!
     
  12. Gyoza_sauce

    Gyoza_sauce Member

    Joined:
    Sep 15, 2017
    Posts:
    38
    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: Nov 3, 2017
    Buff likes this.
  13. Gyoza_sauce

    Gyoza_sauce Member

    Joined:
    Sep 15, 2017
    Posts:
    38
    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: Nov 4, 2017
  14. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
    Gyoza_sauce likes this.
  15. Paul Huckstepp

    Paul Huckstepp Member

    Joined:
    Oct 21, 2017
    Posts:
    20
    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?
     
  16. nigmatech

    nigmatech Guest

    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
     
  17. Paul Huckstepp

    Paul Huckstepp Member

    Joined:
    Oct 21, 2017
    Posts:
    20
    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.
     
  18. Paul Huckstepp

    Paul Huckstepp Member

    Joined:
    Oct 21, 2017
    Posts:
    20
    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.
     
    JAG likes this.
  19. Donkey Kongus

    Donkey Kongus Member

    Joined:
    Dec 17, 2017
    Posts:
    11
    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.
     
  20. Seryal

    Seryal Member

    Joined:
    Nov 4, 2017
    Posts:
    37
    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?
     
  21. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    Hello Seryal,

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

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
  23. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
  24. Seryal

    Seryal Member

    Joined:
    Nov 4, 2017
    Posts:
    37
    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!
     
  25. Donkey Kongus

    Donkey Kongus Member

    Joined:
    Dec 17, 2017
    Posts:
    11
    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.
     
  26. Seryal

    Seryal Member

    Joined:
    Nov 4, 2017
    Posts:
    37
    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!
     
  27. Donkey Kongus

    Donkey Kongus Member

    Joined:
    Dec 17, 2017
    Posts:
    11
    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
     

    Attached Files:

    • fl.png
      fl.png
      File size:
      226 KB
      Views:
      20
    Last edited: Dec 25, 2017
  28. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
  29. Donkey Kongus

    Donkey Kongus Member

    Joined:
    Dec 17, 2017
    Posts:
    11
    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: Jan 2, 2018
  30. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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?
     
  31. Donkey Kongus

    Donkey Kongus Member

    Joined:
    Dec 17, 2017
    Posts:
    11
    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.
     
  32. Seryal

    Seryal Member

    Joined:
    Nov 4, 2017
    Posts:
    37
    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: Jan 14, 2018
  33. wroberts1014

    wroberts1014 Member

    Joined:
    Jan 23, 2018
    Posts:
    2
    Edit: Solved the issue
     
    Last edited: Jan 24, 2018
  34. Nathan Laing

    Nathan Laing Member

    Joined:
    Jul 31, 2016
    Posts:
    355
    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: Feb 3, 2018
  35. NateTheGreat

    NateTheGreat Member

    Joined:
    Jun 21, 2016
    Posts:
    101
    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.
     
  36. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
    NateTheGreat likes this.
  37. NateTheGreat

    NateTheGreat Member

    Joined:
    Jun 21, 2016
    Posts:
    101
    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!
     
  38. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
    NateTheGreat likes this.
  39. JeffJ

    JeffJ Member

    Joined:
    Jun 20, 2016
    Posts:
    337
    I would like to know this as well.
     
  40. Donkey Kongus

    Donkey Kongus Member

    Joined:
    Dec 17, 2017
    Posts:
    11
    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.
     
  41. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     
  42. Niels

    Niels Member

    Joined:
    Jun 22, 2016
    Posts:
    820
    Would also love this for gms2
     
  43. Nephalen

    Nephalen Member

    Joined:
    Feb 26, 2019
    Posts:
    3
    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.
     
  44. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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:
    [​IMG]

    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.
     
  45. Killuado

    Killuado Member

    Joined:
    Jul 18, 2019
    Posts:
    1
    i didn't understand the point caster so, have some way to make an real-time shadow of a animated player?
     
  46. Buff

    Buff Member

    Joined:
    Jun 26, 2016
    Posts:
    63
    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.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice