Subtraction effect to make fake lights.

I’m in the situation when I really need some sort of light in HTML5, even just a fake light would do it.
The easiest way I can think of to create a fake light is “subtraction effect”.

It would work like this:
I would have a top layer with a black sprite with some opacity covering the full screen and I would have a light sprite on top of this black sprite on the same layer and by using subtraction I could subtract the light sprite from the black sprite, basically creating a hole, same size and shape as the light sprite in the black sprite and this way create a fake light effect. Of course subtraction should take in to account also the opacity of the light sprite not just the size and shape.

Most game dev tools out there got some sort of solution for creating fake lights, GD the only one got absolutely nothing to help with this.

Thanks.

You’re right that adding anything that helps us to get light effects (e.g. a game map in the dark with some light torches or etc) would be helpful and very welcome.

As for adding one light, there’s only a way to make one non-shadowed “light” that I can think of by using alpha opacity. That is, to have a black image (can be layer, can be higher zdepth), which has an alpha opacity hole inside of it. That way, “light” can pass through the circle perfectly, while all of the outside light is filtered out by the black image.

Something like this:

Image in gimp with layer mask, where on the layer mask part, a radial gradient is applied.
I would ideally make the entire image have about 90% to 99% opacity so that a little bit of light can pass through the black parts too.

By stretching the circle, we could make a sort of “headlight” effect.

We could also add a 15% yellow tint (15% visible background layer in Gimp):

But using this method to make 2 lights would be difficult (Edit: or moving lights, while possible, you need a lot of black background size).

1 Like

Thanks for the tip but I may want to position the light anywhere on the screen maybe even move it.

It could be done actually if the sprite with the hole would be lot bigger than the actual window size and I would move this huge sprite to position the hole on the screen but the actual size of the image to cover the entire screen anytime can be huge. I’m not sure if it would be ideal to use such a huge sprite in a game.
Also in case I want more than 1 light in my scene just sounds too much trouble to do it this way.

Agreed.

You helped me to write this example (here’s the entire handling code):

Video preview:
streamable.com/84hrp

Obviously it doesn’t look very cool as a shadow! However, it could still be used for some type of games (find the hidden object). With a finer mesh (more shadow objects of finer resolution) it could be modeled to somewhat resemble lights and shadows, but of course it would take way too many resources and cause everything to lag. Still, it might be interesting to take a look at the video. :slight_smile:

Thanks :laughing:
I’m going to give this system some thoughts as I don’t expect to have any better lighting system in GD in near future. Actually, the community requested some sort of lighting system for years so I don’t expect my current request going to change anything.

Unfortunately I have not many choices. I can drop GD and go with something else for this project or I can go with one of the solutions you suggest here.

It might would be not that heavy on resources and cause lag actually. We definitely need to use collision box instead of pixel perfect collision and might check distance between the shadow and the player before checking collision, that way we would not check collision with potentially hundreds of objects but only with a few that more likely going to collide with the player (but checking distance might be just as resource hungry). Also we could use a timer to reduce how frequently checking collision and distance and reduce from 60 times per second to something like 10 or 20 might be enough.
We could also create and delete these shadow objects on the fly as it needed and keep the number of objects in the scene to work with at minimum this way.

I’ll give it a try when I have the time.
I’m appreciate your help.

Regarding collision checking, distance might actually be enough without further collision checking (collision checking is essentially distance or multiple points for sliding polygonal collision such as might be integrated into the physics engine), as you don’t need an exact hit (it’s okay if there’s a zone between the character and the shadow).

The absolutely simplest calculation I know for distance is this:

abs(Y2-Y1+X2-X1)

I don’t know if it’s possible to use instead of the built in distance actions, but this doesn’t use square root, or even square, and will compare the distance between the objects (it’s best to use centre point of the objects as X1-2 and Y1-2) Square root and square formulas are already built into Gdevelop from what I understand, but this one might not be.

It’s possible to take into account a collision boundary by simply adding a condition such as:

if abs(Y2-Y1+X2-X1) < 0 + (AdditionalRadius) then hide object…

However, I’m not sure if we can use this to get the actual closest object.

As for creating and deleting objects, instead of hiding and showing, you should definitely have a way to measure the speed impact (e.g. with timers, measure the time it takes to complete those actions) as creating and deleting may actually do more and cause more lag than just hiding and showing (although that may not be true if there are too many objects on scene). It’s difficult to say, but every optimization effort is worth a try.

Edit: One optimization method might be to create a grid of these shadow objects only near the main object position, and have everything else be 4 large black objects covering the rest of the screen. But this also isn’t too simple, while absolutely doable.

GD got some advanced mathematical expressions to use, so you can do your own calculations.

The project I have in mind would include a relatively huge scene that you can freely walk around and at least 40 shadow objects would be required to be present at all time to cover the whole screen. It is something that need to try and see but creating and deleting objects on the fly may require less resources than having 400 objects in the scene and checking distance with each or even check visibility for each before checking distance and before checking collision :stuck_out_tongue:

I don’t know, maybe even 40 shadow object would be too many to use anyway.

Actually I have just realized I need only 40 in any circumstances. I can put them on a separate layer and this way the whole scene is covered all the time and I don’t need to worry about the number :stuck_out_tongue:

Separate layer is a great idea. Also, if you check the distance, you don’t necessarily need to check for collision too!

If distance < x is already a collision check of limited accuracy. :slight_smile: What I meant by not being sure if you can use my proposed abs check instead of the built in distance check is that if you use an expression check, it might not ‘select’ the object for you, so you can hide it, but in that case you could likely use ‘for each object’.

The separated layer didn’t worked out as I planned but I just tried and if I create 400 objects and do nothing but check the distance to show and hide it, I get 60 FPS on my gaming desktop, 20 FPS on my 7 years old Linux Laptop and 40 FPS on my 2 years old Win 10 Laptop.

My Linux laptop is so old I don’t think anyone use something like that today for other than reading documents so if I get 40-60 FPS on today PC’s it might worth a try.

It seems like I need to use the For each object even if I use the built in distance check :confused:
If I invert the condition it just doesn’t work without For each… so I might try your abs check instead but it is already too late I put it away for now.

I have to admit I’m still sometimes confused about when to use for each. I would normally have to use it always, but Gdevelop has the “select” feature in which it should select one object that satisfies a condition, among many. E.g. if we have 1000 enemies, all moving from left to right, isn’t it enough to have e.g. If Enemy.X() > 1000 then Delete Enemy without using for each? If there are multiple enemies outside of the location, I would presume they would all get deleted in whatever random order, which should be invisible to the user, so the order shouldn’t be important.

I would like to ask about a couple of things:

  1. What is the problem with using layers, does collision check or distance comparison not work between layers, or something else maybe? I haven’t yet used layers with gdevelop much, so it would be good to know.

  2. Regardless of number of boxes used, why do we need any more boxes than it takes to fill out the screen (I mean, why do we need any boxes outside of the screen)? If you have a character and camera movement, then I understand eventually there will be no boxes once you move outside of the initial screen.

Layers would definitely fix this, but we can also position the boxes to follow the camera position on each refresh (or better, each time that the camera moves, update the position of boxes as well to follow camera).

Finally, we are doing pretty serious optimizations here comparing to some other work (e.g. limiting to 40 boxes). It shouldn’t be a big problem to position or check collision against hundreds of low polygon objects. I made a small 3D FPS shooter with polygonal precision collision, bullets firing, effects showing, and it would still work on a Netbook (which is less powerful than modern smartphones) at acceptable FPS. Admittedly, that is using a 3D game engine that compiled to Native Direct X, and not WebGL/HTML 5, and the collision engine was using optimizations to check only the nearest vertices (but still likely in float or even double precision). Possibly WebGL still carries serious limitations. I hope there’s room for improvement, that is, that Gdevelop code can run somewhat faster in the future updates by default.

That said, I just remembered that we can limit our collision check to integers.

So, then we could use this kind of distance check:

[code]X1 = floor(Object.X())
Y1= floor(Object.Y())

X2=floor(Object2.X())
Y2=floor(Object2.Y())

FastDistance=abs(X2-X1+Y2-Y1)[/code]

Then we can check for each object with something like:

If FastDistance < TargetDistance then Hide Shadow
If FastDistance > TargetDistance then Show Shadow

Of course, this doesn’t “fly” as an accurate collision test, and that’s why we have Pythagoras. But here we’re talking about as fast as possible, rather than accurate.

Also, I see that because we’re not using else, we actually perform this comparison (larger/smaller) 2 times. This probably takes nanoseconds as long as the browser assigns priority to the game at that point in time (I would be largely surprised if it takes more), but might take more to do such checks with collision, or other more resource intensive checks.

So, in this case we wouldn’t get any advantage, but let’s say we have a more resource intensive check, and then here’s a way to avoid doing the check twice (for any type of such check):

If ComplexCollision(Object1,Objec2)=1 then variable InCollision=1
if Variable(InCollision)=1 then do...
if Variable(InCollision)=0 then do...
variable InCollision=0

This should actually help with complex collision check, or other intensive calculations.

To be honest I don’t even know. :blush:
In case you are working with object variables, instances and object linking you definitely need for each to find specific instances with specific values and links but in other cases such as the inverted distance check for example, I’m not sure why I need for each to make it work :confused:

What I had in mind is to put only 40 shadow object on a top layer and make the camera move only when the player leave the screen or about to leave. If the player leave or about to leave the screen on the top for example I move the camera up on the Y axis so we can see that part of the scene and we can keep follow the player and this way I though I may able to keep using the same shadow objects over and over again but it is not the case. Even though the sahdow objects are on the top layer, their global position doesn’t seem to change. So if I create an object at position 0,0, even if I move the camera and the object seem to be moved along with it, technically it didn’t move in global space.
So, when I move the camera, the shadow objects just no longer react to distance check and not hiding. I have never done anything like this before so to be honest I don’t even know what am I doing.

I didn’t give up yet :slight_smile: Using only 40 instead of hundreds would be a huge performance boost. If I can not do it this way (probably not) I may try keep moving the shadow objects along with the camera in the actual scene not just keep them on a top layer.

Because the actual scene is bigger than the screen and we can move outside the screen, but yeah we don’t need that many and this is what I’m working on

This is exactly what I’m about to try, thanks for mentioning :slight_smile:

I see where you coming from but it is an HTML5 project actually. If I do a native export it a lot faster but I target HTML5 which is from my experience is a lot slower, that’s why I normally keep a good distance from HTML5. I don’t like it. But, the future of GDevelop with HTML5 seems a bit more promising so I decided to experiment with HTML5 and see if I can come up with something “playable” that runs faster than 8 FPS :smiling_imp:

An oversight, if you check for distance, use:

abs(x2-x1)+abs(y2-y1) to avoid negative/positive signs messing up the result.

Thanks :slight_smile:
I have tried with 40 objects only and move the objects along with the camera.
Now I get stable 60 FPS on my Win 10 laptop too and 30 FPS on my old Linux laptop.
It is in full screen but in case I switch the browser to windowed mode I get almost 50 FPS even on my old Linux laptop :smiley:
Considering HTML5 games most likely played in window (imo) and the laptop got only a 1.3GHz dual core CPU and 128MB Intel GM shared graphics I think it not too bad.

But maybe when I have the time I’m going to try in different engines too and see if I get the same FPS just to be sure.

Glad to hear. :slight_smile: FPS should depend on the browser also. E.g. I get more FPS in Chrome than Firefox in a 3d WebGL demo, but even slightly more FPS in IE (to my surprise).

Of course. I normally use Firefox as my main browser for everything. If something works in Firefox, ideally it should work in all browsers that is supports HTML5 :smiley:

So I don’t normally test multiple browsers but Firefox.

It is really your choice on what to use for testing, some people don’t even test at all (okay, better to say very little). Unfortunately debugging is a bit difficult with HTML 5 (even though browsers have great built in debuggers, but it’s complicated to use the console and debugging with gdevelop directly without a guide), and each time you want to test a small change (I test every small change usually, at least most of the time) you need to wait for compile and sometimes long browser load time. :smiley: I’m not sure how to improve HTML 5 debugging with Gdevelop, but perhaps we could come up with something (in another thread, of course).

Imagine having a huge project that might take up to a few minutes to load (HTTP requests are slow, for each image you get a request, so 360 small images for one object = 360 requests, especially when not specially streamed with HTTP 1.1 or another stream-load method, perhaps a custom script), then making some small changes (e.g. changing font sizes, fixing a typo, etc.) and waiting a few minutes for each check (rather than checking all at once, because if something doesn’t work well, you’re not sure at which step you made the mistake).

For this reason I normally keep the native platform active is well. For preview changes it a bit faster. I’m also preview even small changes to catch any error while it “small” and don’t get too complicated. Native preview helps a bit. Of course need to be careful to make sure we don’t use a native only feature then scratching our head why it doesn’t work in HTML5 :smiley:

In general, in any engines I use regardless what debuggers it comes with, I normally try to design my projects modular. I design small independent modules for each feature that I can simply turn on-off, replace and hook up the variables used in the module to a Text object to see what is happening. The downside though, it might require more variables to use to keep each module independent from each other and share/access information between the modules only that is really necessary. For that purpose, normally I have a “core” module that holds all “public” informations and all modules pull any information shared with others form that module and also use that module to update information for any other modules to be used. I find very easy to find any errors this way because almost always I can isolate any problem for a specific module instead of the whole project.

Depends on what kind of feature the module is for it may going to be a group or an external event in GD so not only logically but also visually can be easily isolated in the project.