Advertisement
christophermcasey

HTML5 Mirrored Platformer JS

Dec 1st, 2013
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Author: Christopher M. Casey
  2. // http://www.christophermcasey.com/
  3.  
  4. // === CNSTANTS === //
  5. var CANVAS_WIDTH = 640;
  6. var CANVAS_HEIGHT = 480;
  7. var HALF_CANVAS_WIDTH = Math.floor(CANVAS_WIDTH/2);
  8. var HALF_CANVAS_HEIGHT = Math.floor(CANVAS_HEIGHT/2);
  9.  
  10. var MIN_PLATFORM_WIDTH = 30;
  11. var MAX_PLATFORM_WIDTH = 75;
  12. var MAX_PLATFORM_HEIGHT = 13;
  13. var NUMBER_OF_PLATFORMS = 151;
  14.  
  15. var CHAOS_WIDTH = 40;
  16. var CHAOS_HEIGHT = 40;
  17. // ================= //
  18.  
  19. var gInstructionText;
  20. var gHealthText;
  21. var gPointsText;
  22. var gSideText;
  23.  
  24. var gCanvas;
  25. var gContext;
  26. var gTimer;
  27.  
  28. var gCanvasLeft = 0;
  29. var gCanvasTop = 0;
  30.  
  31. var gKeyStates = [false,false,false,false];
  32.  
  33. var gGameOver = 0;
  34.  
  35. var gGameStartTime;
  36.  
  37. //---
  38. var gPlayer;
  39. var gPlayerHealth;
  40. var gPlayerPoints;
  41. var gPlatforms = [];
  42. var gChaos = [];
  43.  
  44. var gCurSide = 1;
  45. //---
  46.  
  47. function OnWindowResize()
  48. {
  49.     if (gCanvas)
  50.     {
  51.         gCanvasLeft = window.innerWidth/2 - HALF_CANVAS_WIDTH;
  52.         gCanvasTop = window.innerHeight/2 - HALF_CANVAS_HEIGHT;
  53.         gCanvas.style.left = gCanvasLeft+"px";
  54.         gCanvas.style.top = gCanvasTop+"px";
  55.        
  56.         gInstructionText.style.top = (gCanvasTop - 85) + "px";
  57.         gInstructionText.style.left = gCanvasLeft + "px";
  58.        
  59.         gHealthText.style.top = (gCanvasTop + CANVAS_HEIGHT + 5) + "px";
  60.         gHealthText.style.left = gCanvasLeft + "px";
  61.        
  62.         gPointsText.style.top = (gCanvasTop + CANVAS_HEIGHT + 30) + "px";
  63.         gPointsText.style.left = gCanvasLeft + "px";
  64.        
  65.         gSideText.style.top = (gCanvasTop + CANVAS_HEIGHT + 5) + "px";
  66.         gSideText.style.left = (gCanvasLeft + CANVAS_WIDTH - 190) + "px";
  67.     }
  68.     return true;
  69. }
  70.  
  71.  
  72. function OnMouseDown(e)
  73. {
  74.     if (new Date().getTime()-gGameStartTime < 2000) return false;
  75.     if (gGameOver>0) return false;
  76.    
  77.     var x = e.clientX - gCanvasLeft;
  78.     var y = e.clientY - gCanvasTop;
  79.    
  80.     if (e.button == 0)
  81.     {
  82.     }
  83.     else if (e.button == 2)
  84.     {
  85.         if (x > 0 && x < HALF_CANVAS_WIDTH)
  86.         {
  87.             gCurSide = 1;
  88.             gSideText.innerHTML = "Currently controlling left mirror";
  89.         }
  90.         else if (x < CANVAS_WIDTH)
  91.         {
  92.             gCurSide = 2;
  93.             gSideText.innerHTML = "Currently controlling right mirror";
  94.         }
  95.     }
  96.     return false;
  97. }
  98.  
  99.  
  100. function OnKeyDown(e)
  101. {
  102.     var i,tmp,tmpX,tmpY;
  103.    
  104.     if (new Date().getTime()-gGameStartTime < 2000) return true;
  105.    
  106.     var keynum;
  107.     if (window.event) // IE
  108.         keynum = e.keyCode;
  109.     else if (e.which) // Netscape/Firefox/Opera
  110.         keynum = e.which;
  111.    
  112.     if (gGameOver>0)
  113.     {
  114.         //if (keynum==32
  115.         if (keynum==71)
  116.         {
  117.             gGameOver = 0;
  118.             gKeyStates = [false,false,false,false];
  119.             gPlayerHealth = 100;
  120.             gPlayerPoints = 0;
  121.             gHealthText.innerHTML = "100 Health";
  122.             gPointsText.innerHTML = "0 Points";
  123.             gPlayer = new Player();
  124.             gGameStartTime = new Date().getTime();
  125.            
  126.             gPlatforms.splice(0,gPlatforms.length);
  127.             gChaos.splice(0,gChaos.length);
  128.            
  129.             // ground
  130.             gPlatforms[gPlatforms.length] =
  131.             new Platform
  132.             (
  133.                 0,
  134.                 CANVAS_HEIGHT - MAX_PLATFORM_HEIGHT,
  135.                 HALF_CANVAS_WIDTH,
  136.                 HALF_CANVAS_HEIGHT
  137.             );
  138.            
  139.             // first platform (always the same)
  140.             gPlatforms[gPlatforms.length] =
  141.             new Platform
  142.             (
  143.                 HALF_CANVAS_WIDTH/2 - MAX_PLATFORM_WIDTH/2,
  144.                 CANVAS_HEIGHT - MAX_PLATFORM_HEIGHT - 100,
  145.                 MAX_PLATFORM_WIDTH,
  146.                 MAX_PLATFORM_HEIGHT
  147.             );
  148.            
  149.             // all other platforms...
  150.             for (i=0; i<NUMBER_OF_PLATFORMS; ++i)
  151.             {
  152.                 tmp = gPlatforms[gPlatforms.length-1];
  153.                
  154.                 if (i%50===0 && i!==0)
  155.                 {
  156.                     gPlatforms[gPlatforms.length] =
  157.                     new Platform
  158.                     (
  159.                         0,
  160.                         tmp.y - 100,
  161.                         HALF_CANVAS_WIDTH,
  162.                         MAX_PLATFORM_HEIGHT
  163.                     );
  164.                     continue;
  165.                 }
  166.                
  167.                 if (tmp.y!==gPlatforms[gPlatforms.length-2].y)
  168.                     tmpY = (Math.random()>0.25 ? tmp.y - 100 : tmp.y);
  169.                 else
  170.                     tmpY = tmp.y - 100;
  171.                
  172.                 tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  173.                 if (tmpY===tmp.y)
  174.                 {
  175.                     while ( (tmpX < 0) || (tmpX+MAX_PLATFORM_WIDTH > HALF_CANVAS_WIDTH) || (Math.abs(tmpX-tmp.x) < MAX_PLATFORM_WIDTH*1.6))
  176.                     {
  177.                         tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  178.                     }
  179.                 }
  180.                 else
  181.                 {
  182.                     tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  183.                     while (tmpX < 0 || tmpX+MAX_PLATFORM_WIDTH > HALF_CANVAS_WIDTH)
  184.                         tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  185.                 }
  186.                
  187.                 gPlatforms[gPlatforms.length] =
  188.                 new Platform
  189.                 (
  190.                     tmpX,
  191.                     tmpY,
  192.                     Math.random() * (MAX_PLATFORM_WIDTH-MIN_PLATFORM_WIDTH) + MIN_PLATFORM_WIDTH,
  193.                     MAX_PLATFORM_HEIGHT
  194.                 );
  195.             }
  196.             //---
  197.            
  198.             //---
  199.             // one-time enemy setup
  200.             //var numChaos = Math.round(Math.random()*40)+40;
  201.             var numChaos=75;
  202.             for (i=0; i<numChaos; ++i)
  203.             {
  204.                 gChaos[gChaos.length] = new Chaos
  205.                 (
  206.                     Math.random()*(HALF_CANVAS_WIDTH-CHAOS_WIDTH),
  207.                     (Math.random()*(gPlatforms[gPlatforms.length-1].y)+100)-100,
  208.                     Math.floor(Math.random()*2)+1
  209.                 );
  210.             }
  211.             //---
  212.            
  213.             return false;
  214.         }
  215.         return true;
  216.     }
  217.    
  218.     if (gCurSide===2)
  219.     {
  220.         switch (keynum)
  221.         {
  222.         case 65:
  223.         case 37: // left
  224.             gKeyStates[0] = true;
  225.             gKeyStates[2] = false;
  226.             return false;
  227.             break;
  228.         case 87:
  229.         case 38: // up
  230.             gKeyStates[1] = true;
  231.             gKeyStates[3] = false;
  232.             return false;
  233.             break;
  234.         case 68:
  235.         case 39: // right
  236.             gKeyStates[2] = true;
  237.             gKeyStates[0] = false;
  238.             return false;
  239.             break;
  240.         case 83:
  241.         case 40: // down
  242.             gKeyStates[3] = true;
  243.             gKeyStates[1] = false;
  244.             return false;
  245.             break;
  246.         case 32: // space
  247.             gPlayer.jump();
  248.             return false;
  249.             break;
  250.         }
  251.     }
  252.     else
  253.     {
  254.         switch (keynum)
  255.         {
  256.         case 65:
  257.         case 37: // left
  258.             gKeyStates[2] = true;
  259.             gKeyStates[0] = false;
  260.             return false;
  261.             break;
  262.         case 87:
  263.         case 38: // up
  264.             gKeyStates[1] = true;
  265.             gKeyStates[3] = false;
  266.             return false;
  267.             break;
  268.         case 68:
  269.         case 39: // right
  270.             gKeyStates[0] = true;
  271.             gKeyStates[2] = false;
  272.             return false;
  273.             break;
  274.         case 83:
  275.         case 40: // down
  276.             gKeyStates[3] = true;
  277.             gKeyStates[1] = false;
  278.             return false;
  279.             break;
  280.         case 32: // space
  281.             gPlayer.jump();
  282.             return false;
  283.             break;
  284.         }
  285.     }
  286.     return true;
  287. }
  288.  
  289. function OnKeyUp(e)
  290. {
  291.     if (new Date().getTime()-gGameStartTime < 2000) return true;
  292.     if (gGameOver>0) return true;
  293.    
  294.     var keynum;
  295.     if (window.event) // IE
  296.         keynum = e.keyCode;
  297.     else if (e.which) // Netscape/Firefox/Opera
  298.         keynum = e.which;
  299.    
  300.     if (gCurSide===2)
  301.     {
  302.         switch (keynum)
  303.         {
  304.         case 65:
  305.         case 37: // left
  306.             gKeyStates[0] = false;
  307.             return false;
  308.             break;
  309.         case 87:
  310.         case 38: // up
  311.             gKeyStates[1] = false;
  312.             return false;
  313.             break;
  314.         case 68:
  315.         case 39: // right
  316.             gKeyStates[2] = false;
  317.             return false;
  318.             break;
  319.         case 83:
  320.         case 40: // down
  321.             gKeyStates[3] = false;
  322.             return false;
  323.             break;
  324.         }
  325.     }
  326.     else
  327.     {
  328.         switch (keynum)
  329.         {
  330.         case 65:
  331.         case 37: // left
  332.             gKeyStates[2] = false;
  333.             return false;
  334.             break;
  335.         case 87:
  336.         case 38: // up
  337.             gKeyStates[1] = false;
  338.             return false;
  339.             break;
  340.         case 68:
  341.         case 39: // right
  342.             gKeyStates[0] = false;
  343.             return false;
  344.             break;
  345.         case 83:
  346.         case 40: // down
  347.             gKeyStates[3] = false;
  348.             return false;
  349.             break;
  350.         }
  351.     }
  352.     return true;
  353. }
  354.  
  355. var gLastUpdateTime;
  356. var gFracOfSec;
  357. function OnUpdate()
  358. {
  359.     var curTime,i,j;
  360.    
  361.     // ================ //
  362.     // ==== TIMING ==== //
  363.     // ================ //
  364.    
  365.     curTime = new Date().getTime();
  366.     gFracOfSec = (curTime - gLastUpdateTime)/1000;
  367.    
  368.     // =============== //
  369.     // ==== LOGIC ==== //
  370.     // =============== //
  371.    
  372.     if (gGameOver===0)
  373.     {
  374.         if (curTime-gGameStartTime > 2000)
  375.         {
  376.             gPlayer.move();
  377.             gPlayer.checkCollisions();
  378.         }
  379.        
  380.         for (i=0; i<gChaos.length; ++i)
  381.         {
  382.             gChaos[i].move();
  383.         }
  384.        
  385.         // check for gameover
  386.         if (gPlayerHealth <= 0)
  387.         {
  388.             gGameOver = 2;
  389.             gHealthText.innerHTML = "Game over! Press 'g' to play again.";
  390.         }
  391.         else
  392.         if (gPlayer.y+gPlayer.h <= gPlatforms[gPlatforms.length-1].y)
  393.         {
  394.             gGameOver = 1;
  395.             gHealthText.innerHTML = "You win! Press 'g' to play again.";
  396.         }
  397.     }
  398.    
  399.     // ================= //
  400.     // ==== DRAWING ==== //
  401.     // ================= //
  402.    
  403.     if (gGameOver===0)
  404.     {
  405.         // background
  406.         gContext.fillStyle = "#000000";
  407.         gContext.fillRect(0,0,HALF_CANVAS_WIDTH,CANVAS_HEIGHT);
  408.         gContext.fillStyle = "#ffffff";
  409.         gContext.fillRect(HALF_CANVAS_WIDTH,0,HALF_CANVAS_WIDTH,CANVAS_HEIGHT);
  410.        
  411.         gContext.save();
  412.         gContext.translate(0,(HALF_CANVAS_HEIGHT-gPlayer.y<0 ? 0 : HALF_CANVAS_HEIGHT-gPlayer.y));
  413.        
  414.         // platforms
  415.         for (i=0; i<gPlatforms.length; ++i)
  416.         {
  417.             gPlatforms[i].draw();
  418.         }
  419.        
  420.         for (i=0; i<gChaos.length; ++i)
  421.         {
  422.             gChaos[i].draw();
  423.             if (gChaos[i].exploded)
  424.             {
  425.                 gChaos.splice(i,1); --i;
  426.             }
  427.         }
  428.        
  429.         // player
  430.         gPlayer.draw();
  431.        
  432.         gContext.restore();
  433.     }
  434.    
  435.     // -- rollover for next frame
  436.     gLastUpdateTime = curTime;
  437. };
  438.  
  439.  
  440. window.onload = function()
  441. {
  442.     var i,tmp,tmpX,tmpY;
  443.    
  444.     if (!Modernizr.canvas)
  445.     {
  446.         document.body.innerHTML =
  447.             "Your browser does not support the HTML5 canvas element;<br>"+
  448.             "consider upgrading to the latest version.";
  449.         return;
  450.     }
  451.    
  452.     //---
  453.     // init globals
  454.     gCanvas = document.createElement("canvas");
  455.     gContext = gCanvas.getContext("2d");
  456.     gInstructionText = document.createElement("div");
  457.     gHealthText = document.createElement("div");
  458.     gPointsText = document.createElement("div");
  459.     gSideText = document.createElement("div");
  460.     //---
  461.    
  462.     //---
  463.     // style up the page
  464.     document.body.style.backgroundColor = "#444444";
  465.     gCanvas.style.position = "absolute";
  466.     gCanvas.width = CANVAS_WIDTH;
  467.     gCanvas.height = CANVAS_HEIGHT;
  468.     gCanvas.style.cursor = "crosshair";
  469.     gCanvas.style.border = "2px solid #888888";
  470.    
  471.     gInstructionText.style.position = "absolute";
  472.     gInstructionText.style.color = "#ffffff";
  473.     gInstructionText.font = "normal 20px verdana";
  474.     gInstructionText.innerHTML = "Use arrow keys or WASD to move, spacebar to jump.  Launch yourself off the center divide to blast enemies for points, make it to the top to win.  Walljumping off the outer side is also possible by moving into the wall and pressing spacebar.  Right click on one side of the mirror to shift your controls to match that half.";
  475.     gInstructionText.style.width = CANVAS_WIDTH+"px";
  476.     gInstructionText.style.height = "30px";
  477.    
  478.     gHealthText.style.position = "absolute";
  479.     gHealthText.style.color = "#ffffff";
  480.     gHealthText.font = "normal 20px verdana";
  481.     gHealthText.innerHTML = "100 Health";
  482.     gHealthText.style.width = CANVAS_WIDTH+"px";
  483.     gHealthText.style.height = "30px";
  484.    
  485.     gPointsText.style.position = "absolute";
  486.     gPointsText.style.color = "#ffffff";
  487.     gPointsText.font = "normal 20px verdana";
  488.     gPointsText.innerHTML = "0 Points";
  489.     gPointsText.style.width = CANVAS_WIDTH+"px";
  490.     gPointsText.style.height = "30px";
  491.    
  492.     gSideText.style.position = "absolute";
  493.     gSideText.style.color = "#ffffff";
  494.     gSideText.font = "normal 20px verdana";
  495.     gSideText.innerHTML = "Currently controlling left mirror";
  496.     gSideText.style.width = CANVAS_WIDTH+"px";
  497.     gSideText.style.height = "30px";
  498.    
  499.     OnWindowResize();
  500.     document.body.appendChild(gCanvas);
  501.     document.body.appendChild(gInstructionText);
  502.     document.body.appendChild(gHealthText);
  503.     document.body.appendChild(gPointsText);
  504.     document.body.appendChild(gSideText);
  505.     //---
  506.    
  507.     //---
  508.     // register events
  509.     window.onresize = OnWindowResize;
  510.     document.onkeydown = OnKeyDown;
  511.     document.onkeyup = OnKeyUp;
  512.     document.onmousedown = OnMouseDown;
  513.    
  514.     // fix issues with events not firing after mousedown on Chrome??
  515.     // (this is probably a hack)
  516.     document.onclick = function(){return false};
  517.     document.ondblclick = function(){return false};
  518.     document.oncontextmenu = function(){return false;};
  519.     gCanvas.onclick = function(){return false};
  520.     gCanvas.ondblclick = function(){return false};
  521.     gCanvas.oncontextmenu = function(){return false;};
  522.     gCanvas.onmousedown = function(){return false;};
  523.     //---
  524.    
  525.     //---
  526.     // one-time setup
  527.     gPlayerHealth = 100;
  528.     gPlayerPoints = 0;
  529.     gHealthText.innerHTML = gPlayerHealth+" Health";
  530.     gPlayer = new Player();
  531.    
  532.     // ground
  533.     gPlatforms[gPlatforms.length] =
  534.     new Platform
  535.     (
  536.         0,
  537.         CANVAS_HEIGHT - MAX_PLATFORM_HEIGHT,
  538.         HALF_CANVAS_WIDTH,
  539.         HALF_CANVAS_HEIGHT
  540.     );
  541.    
  542.     // first platform (always the same)
  543.     gPlatforms[gPlatforms.length] =
  544.     new Platform
  545.     (
  546.         HALF_CANVAS_WIDTH/2 - MAX_PLATFORM_WIDTH/2,
  547.         CANVAS_HEIGHT - MAX_PLATFORM_HEIGHT - 100,
  548.         MAX_PLATFORM_WIDTH,
  549.         MAX_PLATFORM_HEIGHT
  550.     );
  551.    
  552.     // all other platforms...
  553.     for (i=0; i<NUMBER_OF_PLATFORMS; ++i)
  554.     {
  555.         tmp = gPlatforms[gPlatforms.length-1];
  556.        
  557.         if (i%50===0 && i!==0)
  558.         {
  559.             gPlatforms[gPlatforms.length] =
  560.             new Platform
  561.             (
  562.                 0,
  563.                 tmp.y - 100,
  564.                 HALF_CANVAS_WIDTH,
  565.                 MAX_PLATFORM_HEIGHT
  566.             );
  567.             continue;
  568.         }
  569.        
  570.         if (tmp.y!==gPlatforms[gPlatforms.length-2].y)
  571.             tmpY = (Math.random()>0.25 ? tmp.y - 100 : tmp.y);
  572.         else
  573.             tmpY = tmp.y - 100;
  574.        
  575.         tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  576.         if (tmpY===tmp.y)
  577.         {
  578.             while ( (tmpX < 0) || (tmpX+MAX_PLATFORM_WIDTH > HALF_CANVAS_WIDTH) || (Math.abs(tmpX-tmp.x) < MAX_PLATFORM_WIDTH*1.6))
  579.             {
  580.                 tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  581.             }
  582.         }
  583.         else
  584.         {
  585.             tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  586.             while (tmpX < 0 || tmpX+MAX_PLATFORM_WIDTH > HALF_CANVAS_WIDTH)
  587.                 tmpX = (tmp.x - 80 - MAX_PLATFORM_WIDTH) + Math.random()*(MAX_PLATFORM_WIDTH + 160 + MAX_PLATFORM_WIDTH);
  588.         }
  589.        
  590.         gPlatforms[gPlatforms.length] =
  591.         new Platform
  592.         (
  593.             tmpX,
  594.             tmpY,
  595.             Math.random() * (MAX_PLATFORM_WIDTH-MIN_PLATFORM_WIDTH) + MIN_PLATFORM_WIDTH,
  596.             MAX_PLATFORM_HEIGHT
  597.         );
  598.     }
  599.     //---
  600.    
  601.     //---
  602.     // one-time enemy setup
  603.     //var numChaos = Math.round(Math.random()*40)+40;
  604.     var numChaos=75;
  605.     for (i=0; i<numChaos; ++i)
  606.     {
  607.         gChaos[gChaos.length] = new Chaos
  608.         (
  609.             Math.random()*(HALF_CANVAS_WIDTH-CHAOS_WIDTH),
  610.             (Math.random()*(gPlatforms[gPlatforms.length-1].y)+100)-100,
  611.             Math.floor(Math.random()*2)+1
  612.         );
  613.     }
  614.     //---
  615.    
  616.     //---
  617.     // start timer
  618.     gGameStartTime = gLastUpdateTime = new Date().getTime();
  619.     gTimer = setInterval(OnUpdate,1000/60);
  620.     //---
  621. };
  622.  
  623.  
  624. // ================================= //
  625. // =========== UTILITIES =========== //
  626. // ================================= //
  627.  
  628.  
  629. function Chaos(x,y,side)
  630. {
  631.     var i;
  632.    
  633.     this.x = x;
  634.     this.y = y;
  635.    
  636.     this.maxY = y + 400;
  637.     this.minY = y - 400;
  638.    
  639.     this.xv = Math.random()*200-100;
  640.     this.yv = Math.random()*50-25;
  641.    
  642.     this.side = side; // 1 = left, 2 = right
  643.    
  644.     this.exploding = false;
  645.     this.exploded = false;
  646.    
  647.     var parts = [];
  648.    
  649.     for (i=0; i<40; ++i)
  650.     {
  651.         parts[parts.length] =
  652.         {
  653.             w : Math.round(Math.random()*7+2),
  654.             h : Math.round(Math.random()*7+2),
  655.             x : Math.random()*(CHAOS_WIDTH-14),
  656.             y : Math.random()*(CHAOS_HEIGHT-14),
  657.             xv : Math.random()*40-20,
  658.             yv : Math.random()*40-20
  659.         };
  660.     }
  661.    
  662.     // cache it for performance
  663.     // (avoid global scope lookup table)
  664.     var ctx = gContext;
  665.    
  666.     this.move = function()
  667.     {
  668.         var tmp;
  669.         if (Math.abs(this.y-gPlayer.y) < CANVAS_HEIGHT)
  670.         {
  671.             for (i=0; i<parts.length; ++i)
  672.             {
  673.                 tmp = parts[i];
  674.                 tmp.x += gFracOfSec * tmp.xv;
  675.                 tmp.y += gFracOfSec * tmp.yv;
  676.                
  677.                 if (!this.exploding)
  678.                 {
  679.                     if (tmp.x+tmp.w > CHAOS_WIDTH)
  680.                     {
  681.                         tmp.x = CHAOS_WIDTH-tmp.w;
  682.                         tmp.xv *= -1;
  683.                     }
  684.                     else if (tmp.x < 0)
  685.                     {
  686.                         tmp.x = 0;
  687.                         tmp.xv *= -1;
  688.                     }
  689.                    
  690.                     if (tmp.y+tmp.h > CHAOS_HEIGHT)
  691.                     {
  692.                         tmp.y = CHAOS_HEIGHT-tmp.h;
  693.                         tmp.yv *= -1;
  694.                     }
  695.                     else if (tmp.y < 0)
  696.                     {
  697.                         tmp.y = 0;
  698.                         tmp.yv *= -1;
  699.                     }
  700.                 }
  701.                 else
  702.                 {
  703.                     if (this.x+tmp.x+tmp.w > HALF_CANVAS_WIDTH)
  704.                     {
  705.                         parts.splice(i,1); --i;
  706.                     }
  707.                     else if (this.x+tmp.x < 0)
  708.                     {
  709.                         parts.splice(i,1); --i;
  710.                     }
  711.                     if (this.y+tmp.y+tmp.h > this.maxY)
  712.                     {
  713.                         parts.splice(i,1); --i;
  714.                     }
  715.                     else if (this.y+tmp.y < this.minY)
  716.                     {
  717.                         parts.splice(i,1); --i;
  718.                     }
  719.                 }
  720.             }
  721.            
  722.             if (parts.length===0)
  723.                 this.exploded = true;
  724.         }
  725.        
  726.         // ---
  727.         if (Math.abs(this.y-gPlayer.y) < CANVAS_HEIGHT*2)
  728.         {
  729.             this.x += gFracOfSec * this.xv;
  730.             this.y += gFracOfSec * this.yv;
  731.            
  732.             if (this.x+CHAOS_WIDTH > HALF_CANVAS_WIDTH)
  733.             {
  734.                 this.x = HALF_CANVAS_WIDTH-CHAOS_WIDTH;
  735.                 this.xv *= -1;
  736.             }
  737.             else if (this.x < 0)
  738.             {
  739.                 this.x = 0;
  740.                 this.xv *= -1;
  741.             }
  742.            
  743.             if (this.y+CHAOS_HEIGHT > this.maxY)
  744.             {
  745.                 this.y = this.maxY-CHAOS_HEIGHT;
  746.                 this.yv *= -1;
  747.             }
  748.             else if (this.y < this.minY)
  749.             {
  750.                 this.y = this.minY;
  751.                 this.yv *= -1;
  752.             }
  753.         }
  754.     };
  755.    
  756.     this.draw = function()
  757.     {
  758.         if (Math.abs(this.y-gPlayer.y) > CANVAS_HEIGHT)
  759.             return;
  760.        
  761.         if (side===1)
  762.             ctx.fillStyle = "#ffffff";
  763.         else
  764.             ctx.fillStyle = "#000000";
  765.        
  766.         var tmp;
  767.         for (i=0; i<parts.length; ++i)
  768.         {
  769.             tmp = parts[i];
  770.             if (side===1)
  771.                 ctx.fillRect(this.x+tmp.x,this.y+tmp.y,tmp.w,tmp.h);
  772.             else
  773.                 ctx.fillRect(HALF_CANVAS_WIDTH+this.x+tmp.x,this.y+tmp.y,tmp.w,tmp.h);
  774.         }
  775.     };
  776.    
  777.     this.explode = function()
  778.     {
  779.         this.exploding = true;
  780.        
  781.         var tmp,vecX,vecY,mag;
  782.         for (i=0; i<parts.length; ++i)
  783.         {
  784.             tmp = parts[i];
  785.            
  786.             vecX = Math.random()-0.5;
  787.             vecY = Math.random()-0.5;
  788.             mag = Math.sqrt(vecX*vecX + vecY*vecY);
  789.             vecX /= mag;
  790.             vecY /= mag;
  791.             mag = (Math.random()>0.5 ? Math.random()*200+200 : -1*(Math.random()*200+200));    //(Math.random()*400)-200;
  792.             vecX *= mag;
  793.             vecY *= mag;
  794.            
  795.             tmp.xv = vecX;
  796.             tmp.yv = vecY;
  797.         }
  798.         this.xv = 0;
  799.         this.yv = 0;
  800.     };
  801. }
  802.  
  803.  
  804. function Platform(x,y,w,h)
  805. {
  806.     this.x = Math.round(x);
  807.     this.y = Math.round(y);
  808.     this.w = Math.round(w);
  809.     this.h = Math.round(h);
  810.    
  811.     // cache it for performance
  812.     // (avoid global scope lookup table)
  813.     var ctx = gContext;
  814.    
  815.     this.draw = function()
  816.     {
  817.         // very simple culling
  818.         if (Math.abs(this.y-gPlayer.y) > CANVAS_HEIGHT)
  819.             return;
  820.        
  821.         ctx.fillStyle = "#000000";
  822.        
  823.         ctx.fillRect
  824.         (
  825.             this.x + HALF_CANVAS_WIDTH,
  826.             this.y,
  827.             this.w,
  828.             this.h
  829.         );
  830.        
  831.         ctx.fillStyle = "#ffffff";
  832.        
  833.         ctx.fillRect
  834.         (
  835.             HALF_CANVAS_WIDTH - this.x - this.w,
  836.             this.y,
  837.             this.w,
  838.             this.h
  839.         )
  840.     };
  841. }
  842.  
  843.  
  844. function Player()
  845. {
  846.     var i,tmp;
  847.  
  848.     this.w = 26;
  849.     this.h = 66;
  850.     //this.x = HALF_CANVAS_WIDTH;
  851.     this.x = 0;//Math.round(HALF_CANVAS_WIDTH/2 - 13);
  852.     this.y = CANVAS_HEIGHT - 66 - MAX_PLATFORM_HEIGHT - 1;//HALF_CANVAS_HEIGHT-33+100;
  853.     this.xv = 0;
  854.     this.yv = 0;
  855.    
  856.     this.wallHit = -1;
  857.     this.justHit = -1;
  858.    
  859.     this.jumping = false;
  860.     this.falling = false;
  861.    
  862.     var nextAnim = 0;
  863.     var curAnim = 0;
  864.     var curFrame = 0;
  865.     var elapsed = 0;
  866.     var tmp;
  867.    
  868.     var checkFall;
  869.    
  870.    
  871.    
  872.     // cache it for performance
  873.     // (avoid global scope lookup table)
  874.     // TODO: do this with other globals
  875.     var ctx = gContext;
  876.    
  877.     this.move = function()
  878.     {
  879.         if (this.jumping || this.falling)
  880.         {
  881.             this.yv -= gFracOfSec * 450; // FIX MAGIC#
  882.            
  883.             if (gKeyStates[0])
  884.             {
  885.                 this.xv -= gFracOfSec * 200; // FIX MAGIC#
  886.             }
  887.             else if (gKeyStates[2])
  888.             {
  889.                 this.xv += gFracOfSec * 200; // FIX MAGIC#
  890.             }
  891.         }
  892.         else if (gKeyStates[0])
  893.         {
  894.             this.xv = -100; // FIX MAGIC#
  895.         }
  896.         else if (gKeyStates[2])
  897.         {
  898.             this.xv = 100; // FIX MAGIC#
  899.         }
  900.         else
  901.         {
  902.             this.xv = 0;
  903.         }
  904.        
  905.         if (this.yv < -1000)
  906.             this.yv = -1000;
  907.    
  908.         this.x += gFracOfSec * this.xv;
  909.         this.y -= gFracOfSec * this.yv;
  910.        
  911.         // trigger walk anim
  912.         if (this.yv === 0 && this.xv !==0 && curAnim!==4)
  913.         {
  914.             nextAnim = 4;
  915.         }
  916.     };
  917.    
  918.     this.checkCollisions = function()
  919.     {
  920.         var cTime;
  921.        
  922.         // with walls...
  923.         if (this.x+this.w > HALF_CANVAS_WIDTH)
  924.         {
  925.             this.x = HALF_CANVAS_WIDTH-this.w;
  926.             this.xv = 0;
  927.             if (nextAnim===4)
  928.                 nextAnim = 0;
  929.         }
  930.         else if (this.x <= 0)
  931.         {
  932.             this.x = 0;
  933.             this.xv = 0;
  934.             if (nextAnim===4)
  935.                 nextAnim = 0;
  936.            
  937.             // explode!
  938.             this.jumping = true;
  939.             this.yv = 300; // FIX MAGIC#
  940.             this.xv = 300; // FIX MAGIC#
  941.             this.wallHit = new Date().getTime();
  942.         }
  943.        
  944.         // with bottom of canvas -- (no longer necessary)
  945.         //if (this.y+this.h > CANVAS_HEIGHT)
  946.         //{
  947.             //this.y = CANVAS_HEIGHT-this.h;
  948.         //}
  949.        
  950.         // ----
  951.        
  952.         // if player is falling...
  953.         if (this.yv < 0)
  954.         {
  955.             for (i=0; i<gPlatforms.length; ++i)
  956.             {
  957.                 tmp = gPlatforms[i];
  958.                
  959.                 // and there is a collision with a platform...
  960.                 if ( !(tmp.x > this.x+20
  961.                 || tmp.x+tmp.w < this.x+6
  962.                 || tmp.y > this.y+66
  963.                 || tmp.y+tmp.h < this.y+60) )
  964.                 {
  965.                     if (this.jumping)
  966.                         nextAnim = 3;
  967.                     this.jumping = false;
  968.                     this.falling = false;
  969.                     this.y = tmp.y - this.h - 1;
  970.                    
  971.                     if (this.yv < -950)
  972.                     {
  973.                         gPlayerHealth = 0;
  974.                         gHealthText.innerHTML = gPlayerHealth+" Health";
  975.                     }
  976.                     else if (this.yv < -750)
  977.                     {
  978.                         if (gPlayerHealth-20 < 0)
  979.                             gPlayerHealth = 0;
  980.                         else
  981.                             gPlayerHealth -= 20;
  982.                         gHealthText.innerHTML = gPlayerHealth+" Health";
  983.                     }
  984.                     else if (this.yv < -600)
  985.                     {
  986.                         if (gPlayerHealth-10 < 0)
  987.                             gPlayerHealth = 0;
  988.                         else
  989.                             gPlayerHealth -= 10;
  990.                         gHealthText.innerHTML = gPlayerHealth+" Health";
  991.                     }
  992.                    
  993.                     this.yv = 0;
  994.                     this.xv = 0;
  995.                 }
  996.             }
  997.         }
  998.        
  999.         // if player WAS on a platform...
  1000.         if (this.yv===0)
  1001.         {
  1002.             checkFall = true;
  1003.             for (i=0; i<gPlatforms.length; ++i)
  1004.             {
  1005.                 tmp = gPlatforms[i];
  1006.                
  1007.                 // check if player is STILL on a platform...
  1008.                 if ( !(tmp.x > this.x+20
  1009.                 || tmp.x+tmp.w < this.x+6
  1010.                 || tmp.y > this.y+67
  1011.                 || tmp.y+tmp.h < this.y+60) )
  1012.                 {
  1013.                     checkFall = false;
  1014.                     break;
  1015.                 }
  1016.             }
  1017.            
  1018.             // if not, start falling!
  1019.             if (checkFall)
  1020.             {
  1021.                 this.falling = true;
  1022.                 this.xv /= 2;
  1023.             }
  1024.         }
  1025.        
  1026.         // enemy collisions
  1027.         cTime = new Date().getTime();
  1028.         for (i=0; i<gChaos.length; ++i)
  1029.         {
  1030.             tmp = gChaos[i];
  1031.            
  1032.             if (tmp.exploding) continue;
  1033.            
  1034.             if (tmp.side===2)
  1035.             {
  1036.                 if ( !(tmp.x > this.x+this.w
  1037.                     || tmp.x+CHAOS_WIDTH < this.x
  1038.                     || tmp.y > this.y+this.h
  1039.                     || tmp.y+CHAOS_HEIGHT < this.y) )
  1040.                 {
  1041.                     //console.log("ow!2");
  1042.                     if (cTime-this.wallHit > 1500 && cTime-this.justHit>1000)
  1043.                     {
  1044.                         if (gPlayerHealth-10 < 0)
  1045.                             gPlayerHealth = 0;
  1046.                         else
  1047.                             gPlayerHealth -= 10;
  1048.                         gHealthText.innerHTML = gPlayerHealth+" Health";
  1049.                         this.justHit = new Date().getTime();
  1050.                     }
  1051.                     else if (cTime-this.justHit>1000)
  1052.                     {
  1053.                         //gChaos.splice(i,1); --i;
  1054.                         tmp.explode();
  1055.                         gPlayerPoints += 10;
  1056.                         gPointsText.innerHTML = gPlayerPoints+" Points";
  1057.                     }
  1058.                 }
  1059.             }
  1060.             else
  1061.             {
  1062.                 if ( !(tmp.x > HALF_CANVAS_WIDTH-this.x
  1063.                     || tmp.x+CHAOS_WIDTH < HALF_CANVAS_WIDTH-this.x-this.w
  1064.                     || tmp.y > this.y+this.h
  1065.                     || tmp.y+CHAOS_HEIGHT < this.y) )
  1066.                 {
  1067.                     //console.log("ow!1");
  1068.                     if (cTime-this.wallHit > 1500 && cTime-this.justHit>1000)
  1069.                     {
  1070.                         if (gPlayerHealth-10 < 0)
  1071.                             gPlayerHealth = 0;
  1072.                         else
  1073.                             gPlayerHealth -= 10;
  1074.                         gHealthText.innerHTML = gPlayerHealth+" Health";
  1075.                         this.justHit = new Date().getTime();
  1076.                     }
  1077.                     else if (cTime-this.justHit>1000)
  1078.                     {
  1079.                         //gChaos.splice(i,1); --i;
  1080.                         tmp.explode();
  1081.                         gPlayerPoints += 10;
  1082.                         gPointsText.innerHTML = gPlayerPoints+" Points";
  1083.                     }
  1084.                 }
  1085.             }
  1086.         }
  1087.        
  1088.         if (gPlayerHealth === 0)
  1089.             nextAnim = 5;
  1090.     };
  1091.    
  1092.     // ------------------------------------------ //
  1093.     // -- enormous freaking list of animations -- //
  1094.     // ------------------------------------------ //
  1095.    
  1096.     var anims =
  1097.     [
  1098.         { // ---- idle ---- // 0
  1099.             frames :
  1100.             [
  1101.                 {
  1102.                     t : 0.00,
  1103.                     rects :
  1104.                     [
  1105.                         0,0, 8, 16, // head
  1106.                        
  1107.                         0,19, 11, 16, //body
  1108.                         0,34, 9, 3,
  1109.                         0,36, 7, 4,
  1110.                        
  1111.                         4,42, 6, 10, // left leg
  1112.                         7,54, 5, 3,
  1113.                         7,59, 8, 3,
  1114.                         6,61, 14, 5,
  1115.                        
  1116.                         12,22, 5, 4, // left arm
  1117.                         17,27, 3, 3,
  1118.                         19,31, 6, 6
  1119.                     ]
  1120.                 }
  1121.             ]
  1122.         },
  1123.        
  1124.         { // ---- jump ---- // 1
  1125.             frames :
  1126.             [
  1127.                 {
  1128.                     t : 0.05,
  1129.                     rects :
  1130.                     [
  1131.                         0,0, 8, 16, // head
  1132.                        
  1133.                         0,19, 11, 16, //body
  1134.                         0,34, 9, 3,
  1135.                         0,36, 7, 4,
  1136.                        
  1137.                         9,39, 6, 8, // left leg
  1138.                         13,49, 5, 3,
  1139.                         11,54, 8, 3,
  1140.                         10,56, 14, 5,
  1141.                        
  1142.                         12,22, 5, 4, // left arm
  1143.                         18,23, 3, 3,
  1144.                         19,25, 6, 6
  1145.                     ]
  1146.                 },
  1147.                 {
  1148.                     t : 0.15,
  1149.                     rects :
  1150.                     [
  1151.                         0,0, 8, 16, // head
  1152.                        
  1153.                         0,19, 11, 16, //body
  1154.                         0,34, 9, 3,
  1155.                         0,36, 7, 4,
  1156.                        
  1157.                         8,38, 6, 5, // left leg
  1158.                         12,44, 5, 3,
  1159.                         10,49, 8, 3,
  1160.                         9,51, 14, 5,
  1161.                        
  1162.                         12,22, 5, 4, // left arm
  1163.                         18,23, 3, 3,
  1164.                         19,16, 6, 6
  1165.                     ]
  1166.                 }
  1167.             ]
  1168.         },
  1169.        
  1170.         { // ---- idlejump ---- // 2
  1171.             frames :
  1172.             [
  1173.                 {
  1174.                     t : 0.05,
  1175.                     rects :
  1176.                     [
  1177.                         0,0, 8, 16, // head
  1178.                        
  1179.                         0,19, 11, 16, //body
  1180.                         0,34, 9, 3,
  1181.                         0,36, 7, 4,
  1182.                        
  1183.                         8,38, 6, 5, // left leg
  1184.                         12,44, 5, 3,
  1185.                         10,49, 8, 3,
  1186.                         9,51, 14, 5,
  1187.                        
  1188.                         12,22, 5, 4, // left arm
  1189.                         18,23, 3, 3,
  1190.                         19,16, 6, 6
  1191.                     ]
  1192.                 }
  1193.             ]
  1194.         },
  1195.        
  1196.         { // ---- endjump ---- // 3
  1197.             frames :
  1198.             [
  1199.                 {
  1200.                     t : 0.025,
  1201.                     rects :
  1202.                     [
  1203.                         0,0, 8, 16, // head
  1204.                        
  1205.                         0,19, 11, 16, //body
  1206.                         0,34, 9, 3,
  1207.                         0,36, 7, 4,
  1208.                        
  1209.                         9,39, 6, 8, // left leg
  1210.                         13,49, 5, 3,
  1211.                         11,54, 8, 3,
  1212.                         10,56, 14, 5,
  1213.                        
  1214.                         12,22, 5, 4, // left arm
  1215.                         18,23, 3, 3,
  1216.                         19,25, 6, 6
  1217.                     ]
  1218.                 }
  1219.             ]
  1220.         },
  1221.        
  1222.         { // ---- walk ---- // 4
  1223.             frames :
  1224.             [
  1225.                 {
  1226.                     t : 0.05,
  1227.                     rects :
  1228.                     [
  1229.                         0,0, 8, 16, // head
  1230.                        
  1231.                         0,19, 11, 16, //body
  1232.                         0,34, 9, 3,
  1233.                         0,36, 7, 4,
  1234.                        
  1235.                         9,39, 6, 8, // left leg
  1236.                         13,49, 5, 3,
  1237.                         11,54, 8, 3,
  1238.                         10,56, 14, 5,
  1239.                        
  1240.                         12,22, 5, 4, // left arm
  1241.                         17,27, 3, 3,
  1242.                         19,31, 6, 6
  1243.                     ]
  1244.                 },
  1245.                 {
  1246.                     t : 0.05,
  1247.                     rects :
  1248.                     [
  1249.                         0,0, 8, 16, // head
  1250.                        
  1251.                         0,19, 11, 16, //body
  1252.                         0,34, 9, 3,
  1253.                         0,36, 7, 4,
  1254.                        
  1255.                         8,38, 6, 5, // left leg
  1256.                         12,44, 5, 3,
  1257.                         10,49, 8, 3,
  1258.                         9,51, 14, 5,
  1259.                        
  1260.                         12,22, 5, 4, // left arm
  1261.                         17,27, 3, 3,
  1262.                         19,31, 6, 6
  1263.                     ]
  1264.                 },
  1265.                 {
  1266.                     t : 0.1,
  1267.                     rects :
  1268.                     [
  1269.                         0,0, 8, 16, // head
  1270.                        
  1271.                         0,19, 11, 16, //body
  1272.                         0,34, 9, 3,
  1273.                         0,36, 7, 4,
  1274.                        
  1275.                         4,42, 6, 10, // left leg
  1276.                         7,54, 5, 3,
  1277.                         7,59, 8, 3,
  1278.                         6,61, 14, 5,
  1279.                        
  1280.                         12,22, 5, 4, // left arm
  1281.                         17,27, 3, 3,
  1282.                         19,31, 6, 6
  1283.                     ]
  1284.                 }
  1285.             ]
  1286.         }
  1287.     ];
  1288.    
  1289.     this.draw = function()
  1290.     {
  1291.         var cTime;
  1292.        
  1293.         elapsed += gFracOfSec;
  1294.        
  1295.         // if the current animation frame is finished...
  1296.         if (elapsed > anims[curAnim].frames[curFrame].t)
  1297.         {
  1298.             curFrame = (curFrame+1)%(anims[curAnim].frames.length);
  1299.            
  1300.             // handle finished animation
  1301.             if (curFrame===0)
  1302.             {
  1303.                 curAnim = nextAnim;
  1304.                 if (this.jumping)
  1305.                     nextAnim = 2;
  1306.                 else
  1307.                     nextAnim = 0;
  1308.             }
  1309.             elapsed = 0;
  1310.         }
  1311.        
  1312.         tmp = anims[curAnim].frames[curFrame].rects;
  1313.        
  1314.         cTime = new Date().getTime();
  1315.         var immune = (cTime-this.wallHit < 1500 || cTime-gGameStartTime < 2100);
  1316.         var flash = 0;
  1317.        
  1318.         if (cTime-this.justHit<200)
  1319.             flash = 1;
  1320.         else if (cTime-this.justHit<400)
  1321.             flash = 0;
  1322.         else if (cTime-this.justHit<600)
  1323.             flash = 1;
  1324.         else if (cTime-this.justHit<800)
  1325.             flash = 0;
  1326.         else if (cTime-this.justHit<1000)
  1327.             flash = 1;
  1328.        
  1329.         // draw the black side
  1330.         if (immune)
  1331.             ctx.fillStyle="#777777";
  1332.         else if(flash===1)
  1333.             ctx.fillStyle="#eeeeee";
  1334.         else
  1335.             ctx.fillStyle="#000000";
  1336.        
  1337.         for (i=0; i<tmp.length; i+=4)
  1338.         {
  1339.             ctx.fillRect
  1340.             (
  1341.                 //this.x+tmp[i],
  1342.                 this.x + HALF_CANVAS_WIDTH + tmp[i],
  1343.                 this.y+tmp[i+1],
  1344.                 tmp[i+2],
  1345.                 tmp[i+3]
  1346.             );
  1347.         }
  1348.        
  1349.         // draw the white side as a mirror of the black side
  1350.         if (immune)
  1351.             ctx.fillStyle="#777777";
  1352.         else if(flash===1)
  1353.             ctx.fillStyle="#111111";
  1354.         else
  1355.             ctx.fillStyle="#ffffff";
  1356.        
  1357.         for (i=0; i<tmp.length; i+=4)
  1358.         {
  1359.             ctx.fillRect
  1360.             (
  1361.                 HALF_CANVAS_WIDTH - this.x - tmp[i] - tmp[i+2],
  1362.                 this.y+tmp[i+1],
  1363.                 tmp[i+2],
  1364.                 tmp[i+3]
  1365.             );
  1366.         }
  1367.     };
  1368.    
  1369.     // perform a jump if possible
  1370.     this.jump = function()
  1371.     {
  1372.         //if (curAnim!==0 && curAnim!==4 || (this.falling===true || this.jumping===true))
  1373.         if (this.x+this.w!==HALF_CANVAS_WIDTH || !gKeyStates[2])
  1374.         {
  1375.             if (this.yv!==0 || this.falling===true || this.jumping===true)
  1376.                 return;
  1377.         }
  1378.        
  1379.         this.jumping = true;
  1380.         nextAnim = 1;
  1381.        
  1382.         if (this.x+this.w===HALF_CANVAS_WIDTH && gKeyStates[2])
  1383.         {
  1384.             this.yv = 400; // FIX MAGIC#
  1385.             this.xv = -150; // FIX MAGIC#
  1386.         }
  1387.         else
  1388.         {
  1389.             this.yv = 300; // FIX MAGIC#
  1390.            
  1391.             if (gKeyStates[0])
  1392.             {
  1393.                 this.xv = -50; // FIX MAGIC#
  1394.             }
  1395.             else if (gKeyStates[2])
  1396.             {
  1397.                 this.xv = 50; // FIX MAGIC#
  1398.             }
  1399.         }
  1400.     };
  1401. }
  1402.  
  1403.  
  1404. function dist(x1,y1,x2,y2)
  1405. {
  1406.     return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
  1407. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement