/*--------------------------------------------
  Raytracing Engine
  C0D3D by Gunnar Leffler
  http://www.leftech.com
  Version 1.0
  You are looking at my code. Shame on you! :)
  Just Kidding of course, I hope you learn something.
  --------------------------------------------*/


var wall_ar;
var wall;
var map;
var scrsize_x = 133;// one fourth of the screen size
var scrsize_y = 100;//half of the screen size;
var plane_spacing = 100;
var a1 = 200; //hero x component
var a2 = 200; //hero y component
var b1 = 0;
var b2 = 0;
var x0;
var y0;
var x1;
var y1;
var theta = 0;
var va = 3.1415/4; //Viewangle
var mapsize;
var cnvs;
var ctx;
//for drawing the walls
var dist = 1;
var wall_panel = 1;
var wall_pos = 1;
var clipping = true;
var level = 1;


function loadtextures()
{
wall_ar = new Array();
wall_ar[1] = new Image(); 
wall_ar[2] = new Image();
wall_ar[1].src="img/random/graphix2.jpg";
wall_ar[2].src="img/random/graphix3.jpg";
}

function initmap ()
{
 
  loadtextures();
  cnvs = document.getElementById("canvas");
  ctx = cnvs.getContext("2d");
  map = new Array();
  get_map();

}


function get_map ()
{
 switch (level)
 {
  case 1: 
  map = 
 [[1,1,1,5,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,3],
  [1,0,0,0,0,0,1,3,0,0,0,0,3,3,3,0,0,0,0,3],
  [1,0,0,0,0,0,1,3,0,0,0,0,3,3,0,0,0,0,0,2],
  [1,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,8],
  [1,0,0,0,0,0,1,3,0,0,0,0,3,3,0,0,0,0,0,2],
  [1,0,0,0,0,0,1,3,0,0,0,0,3,3,3,0,0,0,0,3],
  [1,1,1,1,0,1,1,2,0,2,3,3,3,3,3,3,3,3,3,3],
  [6,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3],
  [6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3],
  [6,0,6,0,6,6,6,6,6,6,6,6,6,6,0,0,0,0,0,3],
  [6,0,6,0,6,7,7,7,7,7,7,7,7,3,3,0,0,0,3,4],
  [6,0,0,0,6,7,0,0,0,0,0,0,0,7,7,3,0,3,3,4],
  [6,6,6,6,6,7,0,1,1,1,0,1,0,0,0,7,0,7,0,4],
  [1,7,7,7,7,7,0,1,0,0,0,1,0,0,0,7,0,7,0,4],
  [8,3,3,3,3,3,0,0,0,2,0,1,0,0,0,7,0,7,0,4],
  [8,0,3,0,0,3,0,1,0,0,0,1,0,0,0,7,0,7,0,4],
  [8,10,2,0,0,3,0,1,1,1,1,1,0,0,0,7,0,7,0,4],
  [9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],
  [8,10,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],
  [3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4]];
  mapsize = 20;
  wall = wall_ar[1];
  break;
  case 2: //right
  map = 
 [[7,7,7,7,7,7,7,7,7,7,7,6,7,3,3,3,3,3,3,3],
  [6,0,0,0,0,0,0,0,0,0,0,0,7,3,3,0,0,0,0,2],
  [7,0,7,7,7,7,7,7,7,7,7,0,7,3,0,0,0,0,0,10],
  [7,0,7,1,1,1,1,7,0,0,7,0,0,0,0,0,0,0,0,2],
  [7,0,7,1,0,0,1,7,0,0,7,0,7,3,0,0,0,0,0,3],
  [7,0,7,1,0,0,1,7,0,0,0,0,7,3,3,0,0,0,0,3],
  [7,0,7,1,0,1,1,7,7,7,7,0,7,3,3,3,3,3,3,3],
  [7,0,5,5,0,5,5,5,5,5,5,0,5,5,5,5,5,5,5,5],
  [6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5],
  [7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5],
  [7,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,4],
  [6,0,0,0,6,7,0,0,0,0,0,0,0,7,7,7,7,7,0,4],
  [6,6,6,6,6,7,0,1,1,1,0,1,0,0,0,7,0,7,0,4],
  [1,7,7,7,7,7,0,1,0,0,0,1,0,0,0,7,0,7,0,4],
  [8,3,3,3,3,3,0,0,0,2,0,1,0,0,0,7,0,7,0,4],
  [8,0,3,0,0,3,0,1,0,0,0,1,0,0,0,7,0,7,0,4],
  [8,2,2,0,0,3,0,1,1,1,1,1,0,0,0,7,0,7,0,4],
  [8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],
  [8,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],
  [3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4]];
  mapsize = 20;
  wall = wall_ar[2];
  a1 = 300;
  a2 = 1800;
  break;
 
  default:
  
}
}

function seek_wall ()
{

          var oldt = 999999;
          var t;
          var i = 0;
            if (b1 != 0)
                for (i = 0; i < mapsize; i++)
                {
                    x0 = i * (plane_spacing);
                    t = (x0 - a1) / b1;
                    if ((t > 0) && (t < oldt))//is the plane ahead of the point
                    {
                        y0 = Math.abs(a2 + t * b2);
                        ym = parseInt((y0 / plane_spacing) % mapsize);
                        if (b1 > 0) xm = i; else xm = Math.abs(i - 1);
                        if (map[xm][ym] != 0)
                        {
                            oldt = t;
                            wall_panel = map[xm][ym]-1;
                            wall_pos = y0 % 100-1;
                            x1 = x0;   
                            y1 = y0;
                        }
                    }
                    
                        y0 = x0;
                        t = (y0 - a2) / b2;
                        if ((t > 0) && (t < oldt))//is the plane ahead of the point
                        {
                            x0 = Math.abs(a1 + t * b1);
                            xm = parseInt((x0 / plane_spacing) % mapsize);
                            if (b2 > 0) ym = i; else ym = Math.abs(i - 1);
                            if (map[xm][ym] != 0)
                            {
                                oldt = t;
                                wall_panel = map[xm][ym]-1;
                                wall_pos = x0 % 100-1;
                                x1 = x0;   
                                y1 = y0;
                            }
                        }
                   }
 return(oldt);
}



function draw_scr()
{
  //ctx.clearRect(0,0,400,200);
  ctx.fillStyle = "rgb(50,100,150)";
  ctx.fillRect (0, 0, 399, 100);
  ctx.fillStyle = "rgb(200, 200, 200 )";
  ctx.fillRect (0, 101, 399, 100);
  var wx1 = Math.cos(theta-va);
  var wy1 = Math.sin(theta-va);
  var wx2 = Math.cos(theta+va);
  var wy2 = Math.sin(theta+va);
  var dx = (wx1-wx2)/133.0;
  var dy = (wy1-wy2)/133.0;
  b1 = wx2;
  b2 = wy2;
  var i = 0;
  var txt = "Theta:"+theta+"va:"+va+" x:"+a1+" y:"+a2+" ";
  for (i = 0;i < scrsize_x;i++)
  {
    dist = seek_wall ();
    draw_line (i,dist,parseInt(wall_pos));
    //debug_line();
    b1 += dx;
    b2 += dy;
  }
  //document.getElementById ("debug").innerHTML = txt;
}

function debug_line ()
{
  ctx.fillStyle = "rgb(200,0,0)"; 
  
  ctx.beginPath();
  ctx.moveTo(a1 /2.5, a2/5);
  ctx.lineTo(x1 /2.5, y1/5);
  ctx.stroke()  



 
}

function draw_line (x,z,pos)
{

if (z == 0) z = 0.1; 
var dz = Math.round(100/(z/150));
 ctx.drawImage(wall,pos+(wall_panel*100), 1, 1, 100, x*3,  scrsize_y-dz,3, 2*dz);

}

function clip (x,y)
{
 var i,j;
 return (map[parseInt(x / plane_spacing)][parseInt(y / plane_spacing)]);
}

function move (dist)
{
 var dx = Math.cos(theta)*dist;
 var dy = Math.sin(theta)*dist;
 if (clipping)
 {
  if (clip (a1+dx*2,a2) != 0) dx = 0;
  if (clip (a1,a2+dy*2) != 0) dy = 0;
 }
 a1 += dx;
 a2 += dy;
}


function keyhandler (e)
 {
 var evtobj=window.event? event : e //distinguish between IE's explicit event object (window.event) and Firefox's implicit.
 var unicode=evtobj.charCode? evtobj.charCode : evtobj.keyCode
 switch (unicode)
 {
  case 37: //left
   theta += 0.2;
   draw_scr();
  break;
  case 39: //right
   theta -= 0.2;
   draw_scr();
  break;
  case 38: //up
    move (15);
   draw_scr();
  break;
  case 40: //down
    move (-15);
    draw_scr();
  break;
  case 99: 
    clipping = !clipping;
  break;
  case 32: 
    if (clip (a1+Math.cos(theta)*25,a2+Math.sin(theta)*25) == 9)
    {
     level++;
     alert("Teleporting to floor"+level);
     get_map();
     draw_scr();
    }
  break;

  default:
  alert (unicode);
}


 }
