Precise Shadowcasting demo

by Ondřej Žára

HTML

<script src="https://raw.github.com/ondras/rot.js/master/rot.js"></script>
Click to toggle cells, move to show FOV. Topology: <select id="topology">
<option value="4">4</option>
<option value="8" selected="selected">8</option>
</select><br/>
<canvas id="canvas"></canvas><br/>
FOV: <span id="fov"></span>ms, draw: <span id="draw"></span>ms

CSS

#canvas { border: 1px solid black; cursor: crosshair; }

JavaScript

var CELL = [12, 12];
var SIZE = [40, 30];
var COLOR_WALL = [40, 40, 40];
var COLOR_FLOOR = [180, 180, 180];
var COLOR_LIGHT = [255, 255, 0];

var CTX = document.querySelector("#canvas").getContext("2d");

CTX.canvas.width = CELL[0]*SIZE[0];
CTX.canvas.height = CELL[1]*SIZE[1];
CTX.fillStyle = "black";

var walls = {};
var lights = {};
var lightPassesCallback = function(x, y) {
    var key = x+","+y;
    return (!(key in walls));
}
    
var toggle = function(x, y) {
    var key = x+","+y;
    if (walls[key]) {
        delete walls[key];
    } else {
        walls[key] = 1;
    }        
}
        
var redraw = function() {
    var t1 = Date.now();
    CTX.clearRect(0, 0, CTX.canvas.width, CTX.canvas.height);
    for (var x=0;x<SIZE[0];x++) {
      for (var y=0;y<SIZE[1];y++) {
        var key = x+","+y;
        var light = lights[key];
        var base = (walls[key] ? COLOR_WALL : COLOR_FLOOR);
        var c = [];
        for (var i=0;i<3;i++) {
          var factor = 0.5;
          if (light) { factor += COLOR_LIGHT[i]*light/255; }
          c[i] = Math.min(255, Math.round(base[i]*factor));
        }
        CTX.fillStyle = "rgb("+c.join(",")+")";
        CTX.fillRect(x*CELL[0], y*CELL[1], CELL[0], CELL[1]);
      }
    }
    var t2 = Date.now();
    document.querySelector("#draw").innerHTML = t2-t1;
}
    
var updateVisibility = function(x, y) {
    lights = {};
           
    var topology = parseInt(document.querySelector("#topology").value);            
    var fov = new ROT.FOV.PreciseShadowcasting(lightPassesCallback, {topology:topology});

    var t1 = Date.now();
    fov.compute(x, y, 15, function(x, y, r, vis) {
      lights[x+","+y] = vis*(1-(r+1)/15);
    });

    var t2 = Date.now();
    document.querySelector("#fov").innerHTML = t2-t1;

    redraw();
}

var getCoords = function(e) {
    var x = e.clientX - CTX.canvas.offsetLeft - CTX.canvas.clientLeft;
    var y = e.clientY - CTX.canvas.offsetTop - CTX.canvas.clientTop
    return...