为什么没有其他块发射?

时间:2016-11-12 22:21:10

标签: javascript html if-statement canvas

我正在制作HTML Canvas游戏(Tron),我希望游戏能够检测到玩家何时到达画布的边框。我有一个if语句,用于检查玩家是否与自己的路径或对手接触,并且工作正常,但是在画布之外的参数(y >= 780)没有&#39}似乎在做任何事情。添加了一个片段。那里有一个用于关键事件处理的库,这不是我的代码(在我做了一些更改之后很可能不再需要库,但这不应该与我的问题有任何关系) 。谢谢你的时间。



/*! keydrown - v1.2.2 - 2016-03-23 - http://jeremyckahn.github.com/keydrown */
!function(a){var b=function(){var b={};b.forEach=function(a,b){var c;for(c in a)a.hasOwnProperty(c)&&b(a[c],c)};var c=b.forEach;b.getTranspose=function(a){var b={};return c(a,function(a,c){b[a]=c}),b},b.indexOf=function(a,b){if(a.indexOf)return a.indexOf(b);var c,d=a.length;for(c=0;d>c;c++)if(a[c]===b)return c;return-1};var d=b.indexOf;return b.pushUnique=function(a,b){return-1===d(a,b)?(a.push(b),!0):!1},b.removeValue=function(a,b){var c=d(a,b);return-1!==c?a.splice(c,1)[0]:void 0},b.documentOn=function(b,c){a.addEventListener?a.addEventListener(b,c,!1):document.attachEvent&&document.attachEvent("on"+b,c)},b.requestAnimationFrame=function(){return a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||function(b){a.setTimeout(b,1e3/60)}}(),b.noop=function(){},b}(),c={A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,ENTER:13,SHIFT:16,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,BACKSPACE:8,DELETE:46},d=b.getTranspose(c),e=[],f=function(){"use strict";function a(a){this.keyCode=a,this.cachedKeypressEvent=null}function c(a,b,c,d){c?a[b]=c:a[b](d)}return a.prototype._downHandler=b.noop,a.prototype._upHandler=b.noop,a.prototype._pressHandler=b.noop,a.prototype.isDown=function(){return-1!==b.indexOf(e,this.keyCode)},a.prototype.down=function(a){c(this,"_downHandler",a,this.cachedKeypressEvent)},a.prototype.up=function(a,b){c(this,"_upHandler",a,b)},a.prototype.press=function(a,b){this.cachedKeypressEvent=b,c(this,"_pressHandler",a,b)},a.prototype.unbindDown=function(){this._downHandler=b.noop},a.prototype.unbindUp=function(){this._upHandler=b.noop},a.prototype.unbindPress=function(){this._pressHandler=b.noop},a}(),g=function(e){"use strict";var g={};g.Key=f;var h=!1,i=Date.now?Date.now:function(){return+new Date},j=i();return g.tick=function(){var a,b=e.length;for(a=0;b>a;a++){var c=e[a],f=d[c];f&&g[f].down()}},g.run=function(c){h=!0;var d=i(),e=d-j;b.requestAnimationFrame.call(a,function(){h&&(g.run(c),c(e,d))}),j=d},g.stop=function(){h=!1},b.forEach(c,function(a,b){g[b]=new f(a)}),b.documentOn("keydown",function(a){var c=a.keyCode,f=d[c],h=b.pushUnique(e,c),i=g[f];if(i){var j=i.cachedKeypressEvent||{};(j.ctrlKey||j.shiftKey||j.metaKey)&&(h=!0),h&&i.press(null,a)}}),b.documentOn("keyup",function(a){var c=b.removeValue(e,a.keyCode),f=d[c];f&&g[f].up(null,a)}),b.documentOn("blur",function(a){b.forEach(e,function(a){var b=d[a];b&&g[b].up()}),e.length=0}),g}(e);"object"==typeof module&&"object"==typeof module.exports?module.exports=g:"function"==typeof define&&define.amd?define(function(){return g}):a.kd=g}(window);

canvas {
  width: 1000px;
  height: 800px;
  margin-left: auto;
  margin-right: auto;
  display: block;
  border: 1px solid black;
}

h1,h2 {
  width: 100px;
  text-align: center;
  margin-left: auto;
  margin-right: auto;
  font-family: sans-serif;
}

h2 {
  border: 5px solid black;
  padding: 5px;
}

h2:hover {
  background-color: #7DF9FF;
  cursor: pointer;
}

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Tron</title>
    <script src="keydrown.min.js"></script>
    <link rel="stylesheet" type="text/css" href="tron.css"/>
  </head>
  <body>
    <h1>TRON</h1>
    <h2>PLAY</h2>
    <canvas height="800px" width="1000px"></canvas>
    <script>
      function game() {
        canvas = document.getElementsByTagName('canvas')[0];
        ctx = canvas.getContext('2d');

        ctx.fillStyle = "blue";
        ctx.fillRect(0,0,20,20);
        ctx.fillStyle = "red";
        ctx.fillRect(980,780,20,20);

        x = 980;
        y = 780;
        a = 0;
        b = 0;

        // P2 Controls

        function moveRight() {
          if(kd.UP.isDown() === false && kd.DOWN.isDown() === false && kd.LEFT.isDown() === false && ctx.getImageData(x+21, y, 1, 1).data[0] !== 255 && ctx.getImageData(x+21, y, 1, 1).data[2] !== 255) {
            x+=10;
            ctx.fillStyle = "red";
            ctx.fillRect(x,y,20,20);
          } else if(ctx.getImageData(x+21, y, 1, 1).data[0] === 255 || ctx.getImageData(x+21, y, 1, 1).data[2] === 255 || x >= 980) {
            alert("Blue wins!");
          }
        }

        kd.RIGHT.down(function() {
          clearInterval(dir2);
          dir2 = setInterval(moveRight, 25);
        });

        function moveLeft() {
          if(kd.UP.isDown() === false && kd.DOWN.isDown() === false && kd.RIGHT.isDown() === false && ctx.getImageData(x-1, y, 1, 1).data[0] !== 255 && ctx.getImageData(x-1, y, 1, 1).data[2] !== 255) {
            x-=10;
            ctx.fillStyle = "red";
            ctx.fillRect(x,y,20,20);
          } else if(ctx.getImageData(x-1, y, 1, 1).data[0] === 255 || ctx.getImageData(x-1, y, 1, 1).data[2] === 255 || x <= 0) {
            alert("Blue wins!");
          }
        }

        kd.LEFT.down(function() {
          clearInterval(dir2);
          dir2 = setInterval(moveLeft, 25);
        });

        function moveUp() {
          if(kd.LEFT.isDown() === false && kd.DOWN.isDown() === false && kd.RIGHT.isDown() === false && ctx.getImageData(x, y-1, 1, 1).data[0] !== 255 && ctx.getImageData(x, y-1, 1, 1).data[2] !== 255) {
            y-=10;
            ctx.fillStyle = "red";
            ctx.fillRect(x,y,20,20);
          } else if(ctx.getImageData(x, y-1, 1, 1).data[0] === 255 || ctx.getImageData(x, y-1, 1, 1).data[2] === 255 || y <= 0) {
            alert("Blue wins!");
          }
        }

        kd.UP.down(function() {
          clearInterval(dir2);
          dir2 = setInterval(moveUp, 25);
        });

        function moveDown() {
          if(kd.LEFT.isDown() === false && kd.UP.isDown() === false && kd.RIGHT.isDown() === false && ctx.getImageData(x, y+21, 1, 1).data[0] !== 255 && ctx.getImageData(x, y+21, 1, 1).data[2] !== 255) {
            y+=10;
            ctx.fillStyle = "red";
            ctx.fillRect(x,y,20,20);
          } else if(ctx.getImageData(x, y+21, 1, 1).data[0] === 255 || ctx.getImageData(x, y+21, 1, 1).data[2] === 255 || y >= 780) {
            alert("Blue wins!");
          }
        }

        kd.DOWN.down(function() {
          clearInterval(dir2);
          dir2 = setInterval(moveDown, 25);
        });

        //  Controls

        function moveD() {
          if(kd.W.isDown() === false && kd.S.isDown() === false && kd.A.isDown() === false && ctx.getImageData(a+21, b, 1, 1).data[0] !== 255 && ctx.getImageData(a+21, b, 1, 1).data[2] !== 255) {
            a+=10;
            ctx.fillStyle = "blue";
            ctx.fillRect(a,b,20,20);
          } else if(ctx.getImageData(a+21, b, 1, 1).data[0] === 255 || ctx.getImageData(a+21, b, 1, 1).data[2] === 255 || a >= 980) {
            alert("Red wins!");
          }
        }

        kd.D.down(function() {
          clearInterval(dir1);
          dir1 = setInterval(moveD, 25);
        });

        function moveA() {
          if(kd.W.isDown() === false && kd.S.isDown() === false && kd.D.isDown() === false && ctx.getImageData(a-1, b, 1, 1).data[0] !== 255 && ctx.getImageData(a-1, b, 1, 1).data[2] !== 255) {
            a-=10;
            ctx.fillStyle = "blue";
            ctx.fillRect(a,b,20,20);
          } else if(ctx.getImageData(a-1, y, 1, 1).data[0] === 255 || ctx.getImageData(a-1, b, 1, 1).data[2] === 255 || a <= 0) {
            alert("Red wins!");
          }
        }

        kd.A.down(function() {
          clearInterval(dir1);
          dir1 = setInterval(moveA, 25);
        });

        function moveW() {
          if(kd.A.isDown() === false && kd.S.isDown() === false && kd.D.isDown() === false && ctx.getImageData(a, b-1, 1, 1).data[0] !== 255 && ctx.getImageData(a, b-1, 1, 1).data[2] !== 255) {
            b-=10;
            ctx.fillStyle = "blue";
            ctx.fillRect(a,b,20,20);
          } else if(ctx.getImageData(a, b-1, 1, 1).data[0] === 255 || ctx.getImageData(a, b-1, 1, 1).data[2] === 255 || b <= 0) {
            alert("Red wins!");
          }
        }

        kd.W.down(function() {
          clearInterval(dir1);
          dir1 = setInterval(moveW, 25);
        });

        function moveS() {
          if(kd.A.isDown() === false && kd.W.isDown() === false && kd.D.isDown() === false && ctx.getImageData(a, b+21, 1, 1).data[0] !== 255 && ctx.getImageData(a, b+21, 1, 1).data[2] !== 255) {
            b+=10;
            ctx.fillStyle = "blue";
            ctx.fillRect(a,b,20,20);
          } else if(ctx.getImageData(a, b+21, 1, 1).data[0] === 255 || ctx.getImageData(a, b+21, 1, 1).data[2] === 255 || b >= 780) {
            alert("Red wins!");
          }
        }

        kd.S.down(function() {
          clearInterval(dir1);
          dir1 = setInterval(moveS, 25);
        });

        kd.run(function () {
          kd.tick();
        });

        dir1 = setInterval(moveD, 25);
        dir2 = setInterval(moveLeft, 25);
      }

      document.getElementsByTagName('h2')[0].addEventListener('click', function(){
        game();
      });
    </script>
  </body>
</html>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:0)

学习编程并不容易,小错误可以使它更像是一件苦差事而非欢乐。

我无法发现这个错误,因为我不能100%确定你想要发生什么。

还有很多不好的事情等着你进一步引发问题。

因此,我没有找到并解决您的问题,而是以更易于管理,更友好的DOM以及更不容易出错的方式重写代码。

你使用的键盘手柄对于你需要的东西来说太过分了,所以顶部有一个简单的键盘处理程序。

我讨厌使用警报。它们可能会导致各种问题,因此我更改了代码以在画布上显示结果。

我没有为每个玩家重复代码,而是添加了一个函数来处理作为对象传递的单个游戏。 player1player2对象包含使玩家唯一的所有内容,并且每个玩家都会调用updatePlayer函数。

还有一个drawPlayer函数可供绘制。

我使用requestAnimationFrame更新游戏,而不是使用计时器。你应该尽量避免使用setInterval和setTimeout它们不能提供良好的动画质量,并且真的可以让时间搞砸了。

播放器键盘处理有点复杂,但起初我以为你想要它遵守规则,“只有当一个移动键关闭时才移动”。例如,当向上和向左按下时你没有动作,当你释放按键时,玩家就会停止(但是我看到你的键盘处理程序在没有按键的情况下给了keydowns“。你可以添加那个行为,如果这就是你的话想要将&(按位和)替换为===,例如if(keyPadBits & UP){变为if(keyPadBits === UP) updatePlayer函数

我在游戏功能的顶部添加了“use strict”。这使得代码运行得更快,但也会迫使您在编码时更加小心,因为规则非常严格。这将阻止您创建代码运行且不报告错误的情况。你可能永远不会发生这个错误,或者可能会发生错误,然后你很难找到它。在严格模式激活的情况下,会报告错误,您可以随时修复它。

(function game() {
    "use strict"; // NEVER CODE WITHOUT THIS LINE or you will live in the hell of a billion bugs
    var canvas = document.getElementsByTagName('canvas')[0];
    //var canvas = document.getElementById('can');
    var ctx = canvas.getContext('2d');
    
    //==============================================================================================================
    // Constants and variables
    // bit positions for keypad 
    const UP = 0b1000;
    const RIGHT = 0b100;
    const DOWN = 0b10;
    const LEFT = 0b1;
    // speeds and sizes
    const MOVE_SPEED = 10;
    const PLAYER_SIZE = 20;
    const PLAY_FIELD_SIZEW = canvas.width - PLAYER_SIZE;
    const PLAY_FIELD_SIZEH = canvas.height - PLAYER_SIZE;
    // Flags game state
    var gameOver = true;  // Must start game as gameover= true or it will not start
    //==============================================================================================================
    // keyboard handler to replace overkill  keydrown lib
    var keys = {};
    var filterKeys = "ArrowUp,ArrowDown,ArrowLeft,ArrowRight,KeyA,KeyS,KeyD,KeyW".split(","); // array of keys to listen to
    function keyboard(event){
        if(filterKeys.indexOf(event.code) > -1){ // filter out unwanted key events
            keys[event.code] = event.type === "keydown";  // true if key down false if not
            event.preventDefault();
        }
    }
    document.body.addEventListener("keydown",keyboard);
    document.body.addEventListener("keyup",keyboard);
    
    
    //==============================================================================================================
    // player restart function
    var restartPlayer = function(){
        this.x = this.start.x;
        this.y = this.start.y;
        this.dx = this.start.dx;
        this.dy = this.start.dy;
        this.crash = false;            
    }        
    // player details
    var player1 = {
        x : 980,       // Should be set to player start positions
        y : 0,
        dx : 0,   // movement direction
        dy : 0,
        start : {x: canvas.width - PLAYER_SIZE, y : canvas.height - PLAYER_SIZE,dx :-1,dy :0},
        crash : false,
        ID : 0,
        col : "red",
        restart : restartPlayer,
    }
    var player2 = {
        x : 0,       // Should be set to player start positions
        y : 0,
        dx : 0,   // movement direction
        dy : 0,
        start : {x: 0, y : 0,dx : 1,dy : 0},
        crash : false,
        ID : 1,
        col : "blue",
        restart : restartPlayer,
    }
    
    //==============================================================================================================
    // check player keys moves if needed and checks for crashes
    function updatePlayer(player){
        debugger
        var keyPadBits = 0;
        // set bits for all keys down
        if(player.ID === 0){ // first player
            keyPadBits |= keys.ArrowUp   ? UP : 0;
            keyPadBits |= keys.ArrowRight? RIGHT : 0;
            keyPadBits |= keys.ArrowDown ? DOWN : 0;
            keyPadBits |= keys.ArrowLeft ? LEFT : 0;
        }else{
            keyPadBits |= keys.KeyW ? UP : 0;
            keyPadBits |= keys.KeyD ? RIGHT : 0;
            keyPadBits |= keys.KeyS ? DOWN : 0;
            keyPadBits |= keys.KeyA ? LEFT : 0;
        }
        // get the movement direction in order of priority
        // Can have diagonals eg if(keyPadBits & (UP+LEFT))
        if(keyPadBits & UP){  // YES that is a single & as a bitwise and operator
            player.dy = -1;
            player.dx = 0;                
        }else if(keyPadBits & DOWN){// YES that is a single & as a bitwise and operator

            player.dy = 1;
            player.dx = 0;                
        }else if(keyPadBits & RIGHT){// YES that is a single & as a bitwise and operator

            player.dx = 1;
            player.dy = 0;                
        }else if(keyPadBits & LEFT){// YES that is a single & as a bitwise and operator

            player.dx = -1;
            player.dy = 0;                
        }
        // check pixel in direction of movement 
        var x = player.x + player.dx + PLAYER_SIZE * (player.dx > 0 ? 1 : 0);
        var y = player.y + player.dy + PLAYER_SIZE * (player.dy > 0 ? 1 : 0);
        var data = ctx.getImageData(x,y, 1, 1).data;
        if(data[0] !== 255 && data[2] !== 255){
            player.x += MOVE_SPEED * player.dx;
            player.y += MOVE_SPEED * player.dy;
            // player has moved so check edge crash
            if( player.x < 0 || player.y < 0 || player.x > PLAY_FIELD_SIZEW || player.y > PLAY_FIELD_SIZEH){ 
                player.crash = true;
            }                
        } else { // player must have crashed if red and blue are on
            player.crash = true;
        }
        
    }
    // draws the player at current position
    function drawPlayer(player){
        ctx.fillStyle = player.col;
        ctx.fillRect(player.x, player.y, PLAYER_SIZE, PLAYER_SIZE);  
    }
    // updates both players    
    function playerUpdate(){
        if(!gameOver){
            updatePlayer(player1);
            updatePlayer(player2);
            // draw both players after both have moved or you would give one player a slight advantage of being
            // invisible at his current position
            drawPlayer(player1);
            drawPlayer(player2);
            if(player1.crash || player2.crash){
                gameOver = true;
                var text = "";
                var col = "black";
                if(player1.crash && player2.crash){  // may be a draw if both crash at the same time
                    text = "It's a draw!";
                }else  if(player1.crash){  
                    text = "Blue wins!";
                    col= "blue";
                }else {
                    text = "Red wins!";
                    col = "red";
                }
                ctx.font = "64px Arial black";
                ctx.textAlign = "center";
                ctx.fillStyle = col;
                ctx.strokeStyle = "black";
                ctx.lineWidth = 4;
                if(col !== "black"){
                    ctx.strokeText(text,canvas.width * 0.5, canvas.height * 0.4);
                }
                ctx.fillText(text,canvas.width * 0.5, canvas.height * 0.4);
                ctx.fillStyle = "black";
                ctx.font = "24px Arial black";
                ctx.fillText("Click 'PLAY' to start again.",canvas.width * 0.5, canvas.height * 0.6 );
            }
        }
    }
    // function to restart the game
    function restartGame(){
        player1.restart();
        player2.restart();
        gameOver = false;
        ctx.clearRect(0,0,canvas.width,canvas.height);
    }

    // main animation loop is called 60 times a second.
    function update(time){
        playerUpdate();
        if(!gameOver){
            requestAnimationFrame(update);
        }
    }
    document.getElementsByTagName('h2')[0].addEventListener('click', function(){
        if(gameOver){
            restartGame();
            requestAnimationFrame(update);
        }
    });
})();  // run the function now (function(){})() is an immediately invoked function
  
      
canvas {
  width: 1000px;
  height: 800px;
  margin-left: auto;
  margin-right: auto;
  display: block;
  border: 1px solid black;
}

h1,h2 {
  width: 100px;
  text-align: center;
  margin-left: auto;
  margin-right: auto;
  font-family: sans-serif;
}

h2 {
  border: 5px solid black;
  padding: 5px;
}

h2:hover {
  background-color: #7DF9FF;
  cursor: pointer;
}
    <h1>TRON</h1>
    <h2>PLAY</h2>
    <canvas height="800px" width="1000px"></canvas>

答案 1 :(得分:-1)

您应该只使用一个循环而不是大量的间隔。 此外,您不需要所有这些重复的功能。 以下是重写游戏以使其发挥作用的一种方法:

&#13;
&#13;
var playButton = document.getElementById('play'),
    out = document.getElementById('out'),
    canvas = document.getElementById('tron'),
    ctx = canvas.getContext('2d'),
    width = 300,
    height = 200,
    p1, p2;

playButton.addEventListener('click', startGame);

canvas.width = width;
canvas.height = height;

function startGame() {
  reset();
  
  p1 = {
    name: 'Player 1',
    x: 0, y: 0, 
    vx: 1, vy: 0,
    size: 20,
    color: 'blue',
    speed: 1
  };

  p2 = {
    name: 'Player 2',
    x: width - 20, y: height - 20,
    vx: -1, vy: 0,
    size: 20,
    color: 'red',
    speed: 1
  };
  
  kd.RIGHT.down(function() { p2.vx =  1; p2.vy =  0; });
  kd.LEFT.down( function() { p2.vx = -1; p2.vy =  0; });
  kd.UP.down(   function() { p2.vx =  0; p2.vy = -1; })
  kd.DOWN.down( function() { p2.vx =  0; p2.vy =  1; });

  kd.D.down(function() { p1.vx =  1; p1.vy =  0; });
  kd.A.down(function() { p1.vx = -1; p1.vy =  0; });
  kd.W.down(function() { p1.vx =  0; p1.vy = -1; });
  kd.S.down(function() { p1.vx =  0; p1.vy =  1; });

  kd.run(loop);
}

function loop () {
  ctx.fillStyle = 'rgba(255,255,255,0.01)';
  ctx.fillRect(0,0,width, height);
  
  drawPlayer(p1);
  drawPlayer(p2);
  
  checkCollisions(p1);
  checkCollisions(p2);
  
  kd.tick();
}

function drawPlayer (p) {
  p.x += (p.vx * p.speed);
  p.y += (p.vy * p.speed);
  ctx.fillStyle = p.color;
  ctx.fillRect(p.x, p.y, p.size, p.size);
}

function checkCollisions (p) {
  if (p.x < 0 || p.x + p.size > width) gameOver();
  if (p.y < 0 || p.y + p.size > height) gameOver();
  if (p.vx === -1 &&
      ctx.getImageData(p.x - 1, p.y, 1, 1).data[1] !== 255) gameOver();
  if (p.vx === 1 &&
      ctx.getImageData(p.x + p.size + 1, p.y, 1, 1).data[1] !== 255) gameOver();
  if (p.vy === -1 &&
      ctx.getImageData(p.x, p.y - 1, 1, 1).data[1] !== 255) gameOver();
  if (p.vy === 1 &&
      ctx.getImageData(p.x, p.y + p.size + 1, 1, 1).data[1] !== 255) gameOver();
  
}

function gameOver () {
  kd.stop();
  out.textContent = 'Game Over';
  canvas.className = 'over';
}

function reset () {
  kd.stop();
  ctx.clearRect(0,0,width, height);
  canvas.className = '';
  out.textContent = '';
}

!function(a){var b=function(){var b={};b.forEach=function(a,b){var c;for(c in a)a.hasOwnProperty(c)&&b(a[c],c)};var c=b.forEach;b.getTranspose=function(a){var b={};return c(a,function(a,c){b[a]=c}),b},b.indexOf=function(a,b){if(a.indexOf)return a.indexOf(b);var c,d=a.length;for(c=0;d>c;c++)if(a[c]===b)return c;return-1};var d=b.indexOf;return b.pushUnique=function(a,b){return-1===d(a,b)?(a.push(b),!0):!1},b.removeValue=function(a,b){var c=d(a,b);return-1!==c?a.splice(c,1)[0]:void 0},b.documentOn=function(b,c){a.addEventListener?a.addEventListener(b,c,!1):document.attachEvent&&document.attachEvent("on"+b,c)},b.requestAnimationFrame=function(){return a.requestAnimationFrame||a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||function(b){a.setTimeout(b,1e3/60)}}(),b.noop=function(){},b}(),c={A:65,B:66,C:67,D:68,E:69,F:70,G:71,H:72,I:73,J:74,K:75,L:76,M:77,N:78,O:79,P:80,Q:81,R:82,S:83,T:84,U:85,V:86,W:87,X:88,Y:89,Z:90,ENTER:13,SHIFT:16,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,BACKSPACE:8,DELETE:46},d=b.getTranspose(c),e=[],f=function(){"use strict";function a(a){this.keyCode=a,this.cachedKeypressEvent=null}function c(a,b,c,d){c?a[b]=c:a[b](d)}return a.prototype._downHandler=b.noop,a.prototype._upHandler=b.noop,a.prototype._pressHandler=b.noop,a.prototype.isDown=function(){return-1!==b.indexOf(e,this.keyCode)},a.prototype.down=function(a){c(this,"_downHandler",a,this.cachedKeypressEvent)},a.prototype.up=function(a,b){c(this,"_upHandler",a,b)},a.prototype.press=function(a,b){this.cachedKeypressEvent=b,c(this,"_pressHandler",a,b)},a.prototype.unbindDown=function(){this._downHandler=b.noop},a.prototype.unbindUp=function(){this._upHandler=b.noop},a.prototype.unbindPress=function(){this._pressHandler=b.noop},a}(),g=function(e){"use strict";var g={};g.Key=f;var h=!1,i=Date.now?Date.now:function(){return+new Date},j=i();return g.tick=function(){var a,b=e.length;for(a=0;b>a;a++){var c=e[a],f=d[c];f&&g[f].down()}},g.run=function(c){h=!0;var d=i(),e=d-j;b.requestAnimationFrame.call(a,function(){h&&(g.run(c),c(e,d))}),j=d},g.stop=function(){h=!1},b.forEach(c,function(a,b){g[b]=new f(a)}),b.documentOn("keydown",function(a){var c=a.keyCode,f=d[c],h=b.pushUnique(e,c),i=g[f];if(i){var j=i.cachedKeypressEvent||{};(j.ctrlKey||j.shiftKey||j.metaKey)&&(h=!0),h&&i.press(null,a)}}),b.documentOn("keyup",function(a){var c=b.removeValue(e,a.keyCode),f=d[c];f&&g[f].up(null,a)}),b.documentOn("blur",function(a){b.forEach(e,function(a){var b=d[a];b&&g[b].up()}),e.length=0}),g}(e);"object"==typeof module&&"object"==typeof module.exports?module.exports=g:"function"==typeof define&&define.amd?define(function(){return g}):a.kd=g}(window);
&#13;
canvas {
  margin-left: auto;
  margin-right: auto;
  display: block;
  border: 1px solid black;
}

canvas.over {
  opacity: 0.5;
}

h1,button, h3 {
  width: 100px;
  text-align: center;
  margin-left: auto;
  margin-right: auto;
  font-family: sans-serif;
}

button {
  display: block;
  background: white;
  font-weight: bold;
  font-size: 110%;
  border: 5px solid black;
  padding: 5px;
  margin-bottom: 10px;
}

button:hover {
  background-color: #7DF9FF;
  cursor: pointer;
}

h3 {
  position: relative;
  top: -130px
}
&#13;
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
  </head>
  <body>
    <h1>TRON</h1>
    <button id="play">PLAY</button>    
    <canvas id="tron"></canvas>
    <h3 id="out"></h3>
  </body>
</html>
&#13;
&#13;
&#13;

请注意,您仍需要进行大量改进,特别是在碰撞功能中,因为它不会检查所有可能的碰撞。