Last active
December 10, 2015 16:39
-
-
Save y-lohse/4462395 to your computer and use it in GitHub Desktop.
Lighting simulation inside a canvas
Built with Cannon: https://github.com/y-lohse/Cannon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>RayCaster</title> | |
<script src="http://code.yannick-lohse.fr/cannon/1/cannon.js"></script> | |
<script src="raycasting.js"></script> | |
</head> | |
<body> | |
<div> | |
Torch Power | |
<input type="range" min="0" max="200" value="80" oninput="torch_power=value;torchlight.size=value;" /> | |
</div> | |
<div> | |
Torch Step | |
<input type="range" min="0" max="200" value="100" oninput="torch_step=value" /> | |
</div> | |
<div> | |
Torch Angle | |
<input type="range" min="0" max="360" value="360" oninput="torch_angle=value" /> | |
</div> | |
<div> | |
Torch Angle Step | |
<input type="range" min="2" max="100" value="20" oninput="torch_angle_step=value" /> | |
</div> | |
<div> | |
<button onclick="DEBUG=(DEBUG)?false:true;">Debug on/off</button> | |
</div> | |
<div id="canvas" style="width: 480px; height: 360px; border: 1px solid black;"></div> | |
<div id="fps">0</div> | |
<div id="logs" style="width: 800px; height: 300px; overflow: auto;"> | |
logs in here | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cannon.include('http://code.yannick-lohse.fr/cannon/1/math.js'); | |
Cannon.include('http://code.yannick-lohse.fr/cannon/1/display.js'); | |
Cannon.include('http://code.yannick-lohse.fr/cannon/1/misc.js'); | |
var canvas, player, raysObject, background, torchlight; | |
var DEBUG = false; | |
var torch_power = 80; | |
var torch_step = 100; | |
var torch_angle = 360; | |
var torch_angle_step = 20; | |
var map = [ | |
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1], | |
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,3,0,3,0,0,1,1,1,2,1,1,1,1,1,2,1,1,1,2,1,0,0,0,0,0,0,0,0,1], | |
[1,0,0,3,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1], | |
[1,0,0,3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,3,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2], | |
[1,0,0,3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1], | |
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,0,0,3,3,3,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2], | |
[1,0,0,0,0,0,0,0,0,3,3,3,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,0,0,3,3,3,0,0,3,3,3,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1], | |
[1,0,0,0,0,0,0,0,0,3,3,3,0,0,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,4,0,0,4,2,0,2,2,2,2,2,2,2,2,0,2,4,4,0,0,4,0,0,0,0,0,0,0,1], | |
[1,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,4,0,0,0,0,0,0,0,1], | |
[1,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,4,0,0,0,0,0,0,0,1], | |
[1,0,0,4,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,4,0,0,0,0,0,0,0,1], | |
[1,0,0,4,3,3,4,2,2,2,2,2,2,2,2,2,2,2,2,2,4,3,3,4,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], | |
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] | |
], tilesize = 15; | |
Cannon.onReady = function(){ | |
Cannon.Logger.autolog('logs'); | |
Cannon.use('*'); | |
canvas = new Cannon.Canvas('canvas'); | |
var mapwidth = map[0].length, | |
mapheight = map.length; | |
var bg = new Rectangle(0, 0, canvas.width, canvas.height); | |
canvas.addChild(bg); | |
background = new Rectangle(0, 0, canvas.width, canvas.height); | |
background.fillStyle = '#EEEEEE'; | |
background.center = [0, 0]; | |
canvas.addChild(background); | |
torchlight = new RadialGradient(torch_power); | |
torchlight.addColorStop(0, new Color(0, 0, 0, 0)); | |
torchlight.addColorStop(.7, new Color(0, 0, 0, .4)); | |
torchlight.addColorStop(1, new Color(0, 0, 0, 1)); | |
for (var i = 0; i < mapwidth; i++){ | |
for (var j = 0; j < mapheight; j++){ | |
if (map[j][i]){ | |
var rect = new Rectangle(i*tilesize, j*tilesize, tilesize, tilesize); | |
background.addChild(rect); | |
} | |
} | |
} | |
player = new Circle(16*tilesize, 10*tilesize, tilesize/2); | |
player.fillStyle = new Color(200,0,0,255); | |
player.strokeStyle = new Color(0,0,0,0); | |
canvas.addChild(player); | |
player.moveSpeed = 2; | |
raysObject = new Cannon.DisplayObject(); | |
canvas.addChild(raysObject); | |
var element = document.getElementById('fps'); | |
canvas.on('canvas:FPS', function(event){ | |
element.innerHTML = event.fps; | |
}); | |
canvas.on('canvas:render', onRender); | |
} | |
function onRender(){ | |
var newX, newY; | |
if (canvas.keyIsDown('up')) newY = player.y-player.moveSpeed; | |
else if (canvas.keyIsDown('down')) newY = player.y+player.moveSpeed; | |
else newY = player.y; | |
//Cannon.Logger.log(canvas.heldKeys); | |
if (canvas.keyIsDown('left')) newX = player.x-player.moveSpeed; | |
else if (canvas.keyIsDown('right')) newX = player.x+player.moveSpeed; | |
else newX = player.x; | |
if (isBlocking(newX/tilesize, newY/tilesize)) return; | |
player.x = newX; | |
player.y = newY; | |
raysObject.childs.length = 0; | |
background.masks.length = 0; | |
var angle = 0; | |
//player.rotation = angle/(Math.PI/180); | |
var rays = []; | |
for (var x = 0; x < torch_angle; x += (torch_angle/torch_angle_step)){ | |
var ray_angle = angle/(Math.PI/180)-90-(torch_angle/2)+x; | |
ray_angle = ray_angle*(Math.PI/180); | |
for (var y = 1; y <= torch_step; y++){ | |
if (isBlocking((player.x+(torch_power/torch_step*y)*Math.cos(ray_angle))/tilesize, (player.y+(torch_power/torch_step*y)*Math.sin(ray_angle))/tilesize)) break; | |
} | |
var impactX = (torch_power/torch_step*y)*Math.cos(ray_angle), | |
impactY = (torch_power/torch_step*y)*Math.sin(ray_angle); | |
rays.push(new Vertex2D(impactX, impactY)); | |
} | |
rays.push(new Vertex2D(rays[0].point.x, rays[0].point.y)); | |
if (!DEBUG){ | |
var shape = new Shape(rays, player.x, player.y); | |
background.addMask(shape); | |
var shape = new Shape(rays, player.x, player.y); | |
shape.fillStyle = torchlight; | |
raysObject.addChild(shape); | |
} | |
else{ | |
var shape = new Shape(rays, player.x, player.y); | |
shape.fillStyle = new Color(0,0,0,0); | |
shape.strokeStyle = new Color(200,0,0,255); | |
raysObject.addChild(shape); | |
} | |
} | |
function isBlocking(x, y){ | |
if (y < 0 || y >= map.length || x < 0 || x >= map[0].length) return true; | |
return (map[Math.floor(y)][Math.floor(x)] != 0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment