Search code examples
javascriptcanvasradial-gradients

Javascript canvas simple lightsource


I'm making a game with javascript canvas. I'm drawing all the game elements, like the player, blocks and lines, but I don't want you to see all that. Instead want the whole screen to be black, expect for in some places where there is lightsources. I don't need any shadows, just a circle on the screen that is lit up with a radial gradient. I am able to achieve this for one lightsource by adding a transparent gradient after I have drawn everything else, like this: (imagine the red rectangle to be all the things in the game)

//Drawing all the game elements 
ctx.fillStyle = "red"; 
ctx.fillRect(100, 100, 400, 300);

//adding the darkness and the lightsources
var grd = ctx.createRadialGradient(150, 100, 5, 150, 100, 100);
grd.addColorStop(0, "transparent");
grd.addColorStop(1, "black");
ctx.fillStyle = grd; ctx.fillRect(0, 0, 600, 400);

JSFiddle

But how can I achieve this with multiple lightsources? The technique showed won't work.

I have tried using the Illuminated.js api, but that was incredibly slow, and I don't need anything of the shadows and all that fancy stuff, just a circle where you can see the game.


Solution

  • Here's an example of my approach - create black&white mask and multiply the base with it:

    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    
    //Drawing all the game elements 
    ctx.fillStyle = "red";
    ctx.fillRect(100, 100, 400, 300);
    
    //adding the darkness and the lightsources
    function addlight(ctx, x, y) {
      var grd = ctx.createRadialGradient(x, y, 10, x, y, 150);
      grd.addColorStop(0, "white");
      grd.addColorStop(1, "transparent");
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 600, 400);
    }
    
    var buffer = document.createElement('canvas');
    buffer.width = 600;
    buffer.height = 400;
    b_ctx = buffer.getContext('2d');
    b_ctx.fillStyle = "black";
    b_ctx.fillRect(0, 0, 600, 400);
    addlight(b_ctx, 150, 100);
    addlight(b_ctx, 350, 200);
    addlight(b_ctx, 450, 250);
    
    ctx.globalCompositeOperation = "multiply";
    ctx.drawImage(buffer, 0, 0);
    <canvas id="myCanvas" width="600" height="400" style="border:1px solid #d3d3d3;">