Created
May 7, 2014 02:34
-
-
Save xldenis/91f990e29b8d5767e0ea to your computer and use it in GitHub Desktop.
Basic Ray Caster
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
<!doctype html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Raycaster test</title> | |
<script> | |
function Polygon(p){ | |
var points = p; | |
this.contains = function(p){ | |
c = false; | |
var j = points.length -1; | |
for(var i =0; i < points.length; i++){ | |
if((points[i].y > p.y) != (points[j].y > p.y) && | |
( p.x < (points[j].x - points[i].x) * (p.y - points[i].y) / (points[j].y - points[i].y) + points[i].x)){ | |
c = !c; | |
} | |
j = i; | |
} | |
return c; | |
} | |
this.draw = function(ctx){ | |
var length = points.length; | |
ctx.beginPath(); | |
for(var i =0; i < length; i++){ | |
ctx.moveTo(points[i].x,points[i].y); | |
ctx.lineTo(points[(i+1) % length].x, points[(i +1)% length].y); | |
} | |
ctx.stroke(); | |
} | |
return this; | |
} | |
//In World Object | |
//Both pos and dir are expected to be 2D vecs | |
function World(context,w,h){ | |
var width = h; | |
var height =w; | |
var polys = []; | |
var ctx = context; | |
function collide(pos){ | |
for(var i = 0; i < polys.length; i++){ | |
if(polys[i].contains(pos)){ | |
return polys[i]; | |
} | |
} | |
} | |
function sign(number){ | |
return number?number<0?-1:1:0; | |
} | |
this.castRay = function(p,ang) { | |
var pos = {x: p.x, y: p.y}; | |
if((pos.x > width || pos.x < 0) || (pos.y > height || pos.y < 0)){ | |
return undefined; | |
} | |
var scaled = {x: Math.cos(ang), y: -1*Math.sin(ang) }; | |
while((pos.x < width && pos.x >= 0) && (pos.y < height && pos.y >= 0)){ | |
var poly = collide(pos); | |
if(poly){return {pos: pos, poly: poly};} | |
pos.x += scaled.x; | |
pos.y += scaled.y; | |
} | |
// return null; | |
return {pos: pos, poly: null}; | |
} | |
this.castRays = function(pos,num){ | |
var dtheta = 2*Math.PI / num; | |
var rays = []; | |
for(var i =0; i < num; i++){ | |
var res = this.castRay(pos,dtheta*i); | |
if(res){ | |
rays.push(res); | |
} | |
} | |
return rays; | |
} | |
this.drawRays = function(pos,num,col) { | |
var rays = this.castRays(pos,num); | |
var prevStyle = ctx.strokeStyle; | |
ctx.strokeStyle = col; | |
ctx.beginPath(); | |
for(var i = 0; i < rays.length; i++){ | |
ctx.moveTo(pos.x,pos.y); | |
ctx.lineTo(rays[i].pos.x,rays[i].pos.y); | |
} | |
ctx.stroke(); | |
ctx.strokeStyle = prevStyle; | |
} | |
this.drawWorld = function(){ | |
ctx.save(); | |
ctx.clearRect(0,0,width,height); | |
for(var i =0; i < polys.length; i++){ | |
polys[i].draw(ctx); | |
} | |
ctx.restore(); | |
} | |
this.addPoly = function(poly) { | |
polys.push(poly); | |
} | |
return this; | |
} | |
function Game(c) { | |
var canvas = document.getElementById(c); | |
var ctx = canvas.getContext('2d'); | |
var world = new World(ctx,canvas.width,canvas.height); | |
var prev_frame; | |
var mousePos = {x: 50, y: 50}; | |
var pos1; | |
this.init = function() { | |
// create random polygons | |
// var p = new Polygon([{x: 100, y: 100}, {x: 100, y:300},{x: 300, y: 300}, {x: 300, y: 100} ]); | |
for(var i = 0; i < 5; i++){ | |
world.addPoly(randomConvex(15)); | |
} | |
prev_frame = Date.now(); | |
gameCycle(); | |
} | |
function gameCycle(){ | |
world.drawWorld(); | |
pos1 = {x: mousePos.x + 150*Math.cos(Date.now() / (500 ) ), y: mousePos.y + 150*Math.sin(Date.now() / (500))}; | |
// world.drawRays(pos1,100,"#0f0"); | |
// world.drawRays(pos1,360,"#00f"); | |
world.drawRays(mousePos,360,"#f00"); | |
prev_frame = Date.now(); | |
window.webkitRequestAnimationFrame(function(t){gameCycle();}); | |
} | |
function randomPolygon(numSides) { | |
points = []; | |
var x = Math.floor(Math.random()*(canvas.width - 200) + 100); | |
var y = Math.floor(Math.random()*(canvas.height -200) + 100); | |
var radius = Math.floor(Math.random()*100); | |
while(points.length != numSides){ | |
var rX = x + Math.floor(Math.random()*radius - radius /2 ); | |
var rY = y + Math.floor(Math.random()*radius - radius /2 ); | |
if(rX > 0 && rX < canvas.width && rY > 0 && rY < canvas.width){ | |
points.push({x: rX,y:rY}); | |
} | |
} | |
return new Polygon(points); | |
} | |
function randomConvex(numSides){ | |
var dtheta = 2*Math.PI / numSides; | |
var x = Math.floor(Math.random()*(canvas.width - 200) + 100); | |
var y = Math.floor(Math.random()*(canvas.height -200) + 100); | |
var angles = []; | |
for(var i=0; i< numSides; i++){ | |
angles.push(Math.random()*2*Math.PI); | |
} | |
var points = angles.sort().map(function(el){ | |
var radius = Math.floor(Math.random()*200); | |
return {x: x+ Math.cos(el)*radius, y: y+ Math.sin(el)*radius}}); | |
console.log(points); | |
return new Polygon(points); | |
} | |
function getMousePos(canvas, evt) { | |
var rect = canvas.getBoundingClientRect(); | |
return { | |
x: evt.clientX - rect.left, | |
y: evt.clientY - rect.top | |
}; | |
} | |
canvas.addEventListener('mousemove',function(e) { | |
mousePos = getMousePos(canvas,e); | |
},false); | |
} | |
window.onload = function() { | |
var g = new Game('test'); | |
g.init(); | |
} | |
</script> | |
</head> | |
<body> | |
<canvas id="test" width="1000" height="1000"></canvas> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment