excaliburjs / Excalibur

🎮 Your friendly TypeScript 2D game engine for the web 🗡️
https://excaliburjs.com
BSD 2-Clause "Simplified" License
1.75k stars 188 forks source link

Add a light type of entity for lighting effects #267

Open eonarheim opened 10 years ago

eonarheim commented 10 years ago

Context

It would be useful to have the ability to utilize dynamic lighting effects.

Proposal

Something like this

// x, y, radius, luminosity
var light = new ex.Light(100, 100, 10, 1);
game.currentScene.addLight(light);
jedeen commented 7 years ago

This might be worth looking at: https://github.com/gre/illuminated.js

github-actions[bot] commented 3 years ago

This issue hasn't had any recent activity lately and is being marked as stale automatically.

luttje commented 2 years ago

I hope you don't mind me bumping this old issue, but I'm looking for something like this. In the meantime while we wait I've got something that may help others looking to light their scenes.

I've conjured up a very cheap way to fake lighting: image

This is the general process:

  1. Overlay the game canvas with another canvas (#lightingCanvas), match the game canvas size and position
  2. Paint the whole #lightingCanvas translucently black (this mimics darkness)
  3. Ask all objects which type of 'light mask' they emit and where. Example mask: spot
  4. Using globalCompositeOperation = 'destination-out' cut out the lit part from the darkness on the #lightingCanvas

Objects can register their lighting in their constructor like this:

const lightSprite = Resources.light_Spot.toSprite();
LightingManager.instance.on(LightingEventTypes.RegisteringLights, (ev) => {
  // This event handler is called everytime lighting is updated

  // Let this big light be drawn:
  ev.lightingManager.registerLight(
    new GraphicLightEmitter({
      pos: this.pos,
      graphic: lightSprite,
      scale: vec(5, 5)
    })
  );
});

I quickly made a little demo based on the platformer demo and it's custom-loader.ts shows how to light the whole screen on loading.

Of course it isn't realistic lighting at all, but for some style of pixel art it may just be enough.

I hope this helps someone.

eonarheim commented 2 years ago

@luttje Wow this is very cool!

Autsider666 commented 2 weeks ago

Giving this old issue another bump by giving a +1 to the globalCompositeOperation = 'destination-out' method.

I've experimented with this topic a lot the past few months and I managed to get light occluding objects to work in my latest experiment. (Video of end result)

The light mask is handled using createRadialGradient, but it should work with sprites as well.

The light occlusion is handled by a field-of-view polygon build on top of this example, calculated by raycasting to every visible edge point of every light blocking object twice, each with a very small (0.000001) positive and negative offset. A lot of this process is "cached" by storing the points in the new(ish) Path2D.

I've gathered a large, chaotic list of resources about this subject, so give me a shout if it's useful if I compile it into something more useful for general usage.

eonarheim commented 2 weeks ago

@Autsider666 Lighting effects are definitely something I want in Excalibur.

Some low hanging fruit might be to add cookbook/tutorials to the docs on how to achieve effects like your video! (Which is awesome by the way).

Some ideas I've been kicking around involve ECS style things:

Not sure if we'd have a single lighting system or multiple for each effect

I've gathered a large, chaotic list of resources about this subject, so give me a shout if it's useful if I compile it into something more useful for general usage.

Definitely send that over! It would 1000% be useful