Not logged inGosu Forums
Forum back to Help Search Register Login
Up Topic Gosu / Gosu Exchange / How could I create a Flashlight effect ?
- - By bestguigui Date 2013-06-27 08:03 Edited 2013-06-27 08:12
Hello there !

Yesterday I created that thing bellow (all 2D using only Gosu drawing methods) :

The idea is that the background is rendered illuminated, then the player is drawn and a torchlight sprite is drawn on top of it. The noise effect is another layer drawn on top of everything. The torchlight is made like this :

The surrounding black is partially transparent and the "light part" is even more transparent. The sprite is drawn using Gosu::Image.draw_rot. I created a method that draws the corners so that when the sprite is rotated, the global image is still a rectangle. The fill color for the edges is the same partially transparent black used before. Finally, from this englobing rectangle, 4 rectangles are drawn the same color to cover the entire screen.

Things are working great, there are some frames where I see glitches, really one or two frames a minute, randomly, which is annoying but I can live with that.

The only problem here is that I can't use this technique if I want to add other "light layers". It works here because everything is dark except the torlight area, but I would like to add other light sources and it would be really hard to use the same technique, taking care of other rectangles intersecting the ones drawn for the torchlight.

Is there another way to create this effect ? I would really like to use only Gosu drawing techniques. Thanks for your precious help.
Parent - - By oli.obk Date 2013-06-27 08:35
good job.

instead of drawing many textures i advise to make your light rectangle even bigger so it'll cover the whole screen in any rotation and position. then you'd get rid of the glitches.
or you could slightly overlap the corners of your rectangles to prevent light spots from appearing (in the dark part you'd have dark lines, which would be less noticable than bright glitches)

for drawing multiple layers you'd need some kind of render to texture feature with your method. you'd draw all your lights, create an image from that, clear the screen, draw all your objects, draw the light image over the objects. This could be done easily by abusing the various possible screenshot methods (search this board for some of them). of course, this might not be very performant.
Parent - - By bestguigui Date 2013-06-27 08:47
Thanks for your reply :)

I thought about creating a big image first, but since I'm used to create the smallest files possibles, I considered it would be better to go the way I did for performance issues, even if I know that it's not good to optimize anything until an issue is detected, and I don't know if drawing multiple rects is really faster than one huge one.

Using the Gosu::Window#record could be an option then. But still : if the background is rendered to a texture using whatever method available, the black part of my torchlight would overide lighted areas from the "screenshot". Then what I would really need to achieve that effect is that only the light from the torchlight is rendered, kinda used as an alpha mask. It's this effect that I couldn't get that got me to code this tricky way to draw it.
Parent - - By jlnr (dev) Date 2013-06-27 11:40
I don't think you can achieve that using record, and rendering all lights to a texture every frame sounds slow too… I think your best bet is to look at Spooner's Ashton gem, which even contains a small (very different) lighting system.
Parent - - By bestguigui Date 2013-06-27 11:47
I agree with you that Ashton would be the better choice :)
I don't know anything about shaders, my point was to create something looking cool using only Gosu primitive drawing methods. The lights would be set once for all, I don't want any other "dynamic light" than the torchlight itself... I'll think about it some more ;)
Parent - By oli.obk Date 2013-06-27 12:26
well… if you don't mind some loss in colour you can create 3 layers: background, background light, flashlight

then try playing around with different alphamodes (additive vs multiplicative) for the light layers, different amounts of alpha for the darkness and different orders of application of the light layers
Parent - - By oli.obk Date 2013-06-27 12:29
actually in my use cases gosu is very fast when screencapping stuff and when updating textures every frame.
i have stuff like 1000fps when drawing an array to a texture every frame and drawing that texture (on my crappy notebook!)
note: that texture wasn't very big, only 128x128 iirc
Parent - - By bestguigui Date 2013-06-27 12:44
I tried to replace my light image with a gigantic one. There is no lag at all, and that prevents me to draw all that maths corrections with rotation and rectangular fill. This hurts because it was not that easy to code for me.

I have an idea mixing all your ideas. I should maybe seperate my black layer part of the lamp and the highlight in the center, that way I could :
- render to Z = 0 the background that should be affected by darkness
- render to Z = 2 the background that shouldn't be affected by darkness (where there is already lights)
- render to Z = 1 the black mask of the light image
- render to Z = 3 the light part of my mask

That could do the trick. I'll try it out.
Parent - - By oli.obk Date 2013-06-27 15:10
hmm i don't really see how that'll work (better?), but i might be misinterpreting what you're doing, let us know how it goes.

anyway, try drawing a white circle with multiplicative alpha over a part that's already darkened, it should brighten up dark spots (with colour loss)
Parent - By bestguigui Date 2013-06-27 18:14 Edited 2013-06-27 19:35

I'm playing with my idea. For now, the basic effect will do it. I'm looking for a way to the gameplay I have in mind.

WASD to move
Mouse : right click (light ON / OFF), up / down (aim), left / right (change direction, may need some improvement).

The character will walk faster forward and slower if he walks backwards and / or diagonally.

The left click will able to shoot, but not yet :)
Collisions are not handled yet, I'm not sure how I'll create my maps for now.

EDIT : you can "shoot" using the left click (only a muzzle flash and a sound effect for now, it gives an idea). I added some sound effect to try out an ambiance. The character is temporary.
Parent - - By jlnr (dev) Date 2013-06-27 18:38
As far as I know, multiplicative mode works in the 0..1 range, so multiplying with white = 1 will not brighten up anything.
Parent - - By bestguigui Date 2013-06-27 19:34
Thanks ! I'll use that info when I decide how I create my maps. I have an idea with this "game", but it's not easy ;)
Parent - - By Spooner Date 2013-06-27 23:37
I found the best lighting effect was from using multiply. 1 will show the graphics "normally" and fractions will put it into darkness.

@jlnr: Sadly, my lighting engine is broken. Would be great if it did work though (as it so nearly does, but the maths is broken somewhere and I haven't a clue where)!

EDIT: additive tends to wash out colours and just drawing dark grey (using default blending) over it tends to make everything too grey.
Parent - - By bestguigui Date 2013-06-28 07:40
When you say "1", do you mean pure white, or pure opaque alpha ?
Parent - By Spooner Date 2013-07-01 13:27
I mean white rgba(255, 255, 255, 255), sorry. That will not affect the underlying image when multiplied (since it is x1). The darkest part of the room should be rgba(255, 255, 255, 0). so that it multiplies the background by x0 so it is effectively removed.
Up Topic Gosu / Gosu Exchange / How could I create a Flashlight effect ?

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill