Skip to content

Instantly share code, notes, and snippets.

@xldenis
Created May 7, 2014 02:34
Show Gist options
  • Save xldenis/91f990e29b8d5767e0ea to your computer and use it in GitHub Desktop.
Save xldenis/91f990e29b8d5767e0ea to your computer and use it in GitHub Desktop.
Basic Ray Caster
<!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