Problem with Lights

Started by Miori, Sun 16/02/2014 12:36:29

Previous topic - Next topic

Miori

Well, I have a problem with lights. Sometimes it should be night in my game, so the screen gerts dark. So I want my character to have a light circle around itself. Thats not the problem. I could take a big dark pic with a hole at characterposition following it. BUT ... even in the night there are other static light sources like lamps or candles.

So there should be static lights in the background, that can't move + one light following the players position and I have no clue how to do something like this :shocked: Could anyone help me please ???


Khris

If you don't need smooth edges, you could use a DynamicSprite and each loop clear it to black, then draw magenta circles to it. Then set the resulting image to a non-clickable GUI.

Miori

Flashlight module is nice :). Tried it and it works finde, but... its only one light. :(

@Khris
Mh, smooth edges would be fine, but I'm not even able to try as you say XD. Could you show me how to do so, please? :)

Khris

First you'll need some way of storing the positions and radii of the light sources in each room.
A very basic way would be this:
Code: ags
// global header 
import int ls_count;
import void SetLightSource(int i, int x, int y, int r);

// global script
int ls_x[20], ls_y[20], ly_r[20];
int ls_count;
export ls_count;

void SetLightSource(int i, int x, int y, int r) {
  ls_x[i] = x; ls_y[i] = y; ls_r[i] = r;
}


In your room's before fadein event, you can now do this:
Code: ags
  ls_count = 3;
  SetLightSource(0, 130, 67, 25);  // index, room coordinates, radius
  ...


Now you need to update the dynamic sprite:
Code: ags
// global script
DynamicSprite *darkness;
void DrawDarkness() {
  if (darkness == null) darkness = DynamicSprite.Create(System.ViewportWidth, System.ViewportHeight);
  DrawingSurface *ds = darkness.GetDrawingSurface();
  ds.Clear(0); // black
  ds.DrawingColor = Game.GetColorFromRGB(255, 0, 255); // magic pink
  int xo = GetViewportX();
  int yo = GetViewportY();
  int i = 0;
  while (i < ls_count) {
    ds.DrawCircle(ls_x[i] - xo, ls_y[i] - yo, ls_r[i]);
    i++;
  }
  // player
  ds.DrawCircle(player.x - xo, player.y - yo - 20, 20); // adjust y and r
  ds.Release();
  gDarkness.BackgroundGraphic = darkness.Graphic;
}

// in repeatedly_execute_always
  if (it_is_night) DrawDarkness();
  gDarkness.Visible = it_is_night;


This code requires a screen-sized GUI called gDarkness and a bool called it_is_night.

Miori

:~( Well, even if I understand how it works, i could never write such a script by myself, I guess there is still much to learn.  :-D It works fine, it is exactly what I was looking for. Thank you so much ;-D 

But I have still some questions. First... I had to downgrade my game to 16-bit to make the magic pink work. But some other graphics, that had smooth transparency effects doesn't look so well anymore. Is it possible to change the bit-rate only for the darkness/light effect and leave 32-bit for the others somehow?

Could we draw another bigger (or smaller if its easier) circle with lower transparency on the position of the light spot, so the contrast between light and dark is not that hard? For an effect like this:


Khris

That's the thing; while AGS can draw semi-transparent stuff, it can only do so if the surface it draws to already has pixels on it. If you draw semi-transparent stuff to an empty/transparent sprite, the result looks like you had drawn on top of magic pink.

There is a plugin called AGSBlend that addresses this, and I believe AGS 3.3.0 has also support for this now. I haven't really used that yet though.
Another problem is that one has to essentially draw holes into a black background. This is easier said than done though, because afaik one can't draw a semi-transparent circle with DrawCircle, one has to use a sprite. But drawing a semi-transparent sprite will not overwrite the pixels below it. One would have to draw sprites like from your post on an empty surface, then fill the area in between with black. But what if two circles overlapped...? etc. etc. ;-D
I'll try a few things and get back to you.

Snarky

Quote from: Khris on Tue 18/02/2014 17:59:45
That's the thing; while AGS can draw semi-transparent stuff, it can only do so if the surface it draws to already has pixels on it. If you draw semi-transparent stuff to an empty/transparent sprite, the result looks like you had drawn on top of magic pink.

Isn't that what the latest version fixes, wrt transparency?

Khris

#8
Yeah, I did mention this and I'm trying a few things in 3.3.0 right now.

Miori: for now, if you replace Game.GetColorFromRGB(...) with COLOR_TRANSPARENT, you should be able to switch back to 32-bit.


Edit:
[IMGZOOM]http://i.imgur.com/cFXLssl.png[/IMGZOOM]

I put it in module form for now, so remove all the other code and add this: click (requires AGS 3.3.0!)

Use it like this:
Code: ags
function room_Load()
{
  Darkness.SetDarkness(80); // 0: off, 100: full black
  Darkness.SetCount(2);
  Darkness.SetLightSource(0, 93, 82, 80, 4);  // index, x, y, radius, flickering
  Darkness.SetLightSource(1, 233, 81, 100, 4);
  Darkness.SetPlayerLight(true, 0, -40, 40);  // on/off, x offset, y offset, radius
}

Miori

Mh... it looks really well ;-D... on the screenshot :-D. I upgraded to AGS 3.3.0 and added your module. For testing I just copied your code and set the "it_is_night"-variable as true. But nothing happens ??? (except lags, but i guess it depends on my lame notebook, where almost every game is lagging XD). Is there something else I have to do :o?

Khris

I've removed a few redundant things: https://www.dropbox.com/s/ytuafvh45s1yuvk/Darkness_0.1_AGS_330.scm

You don't need is_it_night any longer; as long as the darkness is set to something other than 0, it should show up.
Is your game changed back to 32bit?
Did you remove all the previous code? If you didn't, it will interfere.

Miori

#11
I use a backup I made before implementing your codes, so there is none of them left and it is still 32bit. But it still does nothing :o The call functions are placed in room_load(), but I guess it doesn't matter where to place them right? Could also call it from elsewhere? (like turning a switch off or something). There are no errors, after all. It's just not getting dark :o

Is there anything I have to consider with the gDarkness GUI? It's Screensized (640x480) and normally off, with no background or border and not clickable of course :).

edit:

Aaaah, found the problem. I had to put sprite alpha rendering style to the new option too :D Now it works. And uh... the static lights are ... ah... missing english vocabulary, sry. I hope you know what I mean. It just looks awesome now :D

But there is still a small problem. I had an similiar bug when I was testing the flashlight script. The Light thats following the player is running away from him D: Maybe its caused by the smooth scrolling script I use:

Click here

I solved it in the flashlight script somehow... but I can't remember how :- XD Well I have to leave for now T_T I hate that... when i'm in the middle of bug-research XD

Khris

I forgot to subtract the viewport for the player's light. I have updated the module but it's a very quick fix: in lines 70 and 71, change "player.x" to "(player.x - xo)" and "player.y" to "(player.y - yo)".

Btw, if you want a light to not flicker, pass 0 as the last parameter. It's basically the magnitude of the random size change.

Miori

Ah thanks, now everything seem to work. Its so cool, and I love the flicker-effect (laugh) But of course its good that I can turn it off for electric lights and stuff, that should not flicker XD Thank you very much for that awesome module and all the work behind it :D You're a genius. :-*

Khris

Gern geschehen :)

Couldn't have happened without CW and the other awesome people who fixed alpha blending though. This module was written in ten minutes and it's really simple, but I'm glad everything works :)
How's the lagging? Because one could add a few more layers of semi-black to make the transition much smoother still.

Miori

:-D

One more layer for smoother light would be fine, but it is already laggy with this one. My computer is a bit lame and almost every programm and game is lagging here. So it's hard to say :-\ I will test it on the pc of my roomy later ^^.

Miori

#16
Seems not to be laggy :D We could try a second semi-black layer :D

And yes you are right. The Team that made AGS 3.3 did very well with the new version ^_^

Edit:

There seem to be a little problem with the script :o I put the call scripts into a room, just for testing. Everything worked fine. But then I deleted the call scripts. I didn't change anything else. Now the room is always dark :O I put "gDarkness.Visible = false;" in the executive_always section. At least I see something again XD But why does it stay black even after closing the game D:

Khris

#17
You need to use Darkness.SetDarkness(0); in room_Load to turn it off.

I'll make a few tests regarding more layers. :)

Done:
[IMGZOOM]http://i.imgur.com/AEl1Ug4.png[/IMGZOOM]
Darkness v0.3

Added
Code: ags
  Darkness.SetNumberOfLayers(5); // 0 - 20

It's the number of inbetweens, so a setting of 0 means no gradient.

Miori

Ah it looks much greater than before. I also tried the 20 layers limit. That looks really smooth. But I had to wait over a minute for my game to start, and the lags where awfull. I guess for my pc 2 layers are the accepable lag limit XD But well... not everyone has that lame pcs, so I guess I will put it into my option menu, so players can choose the smoothness by themself ^^ Thank you again :D

Besides... is it lagging on your pc too?

Khris

You had to wait a minute for the game to start...? I can understand why it would lag, but that shouldn't happen.
Not lagging for me no :) I'm getting a straight 40FPS even with 20 layers :-D

SMF spam blocked by CleanTalk