简体   繁体   中英

HTML5 Canvas - Keyboard keys do not respond

I'm trying to implement key input in my ping-pong game. The main point is that the up and down arrow keys don't work at all. My browser console doesn't display any errors messages.

Here is my code, this is WIP some Objects are not implemented yet

   var playerBat = {
      x: null,
      y: null,
      width: 20,
      height: 80,
      UP_DOWN: false,
      DOWN_DOWN: false,

      update: function() {
        // Keyboard inputs
        window.addEventListener('keydown', onKeyDown, false);
        window.addEventListener('keyup', onKeyUp, false);

        var key = {
          UP: 38,
          DOWN: 40
        };

        function onKeyDown(e) {
          if (e.keyCode == 38)
            this.UP_DOWN = true;

          else if (e.keyCode == 40)
            this.DOWN_DOWN = true;
        }

        function onKeyUp(e) {
          if (e.keyCode == 38)
            this.UP_DOWN = false;

          else if (e.keyCode == 40)
            this.DOWN_DOWN = false;
        }

        this.y = Math.max(Math.min(this.y, Canvas_H - this.height), 0); // Collide world bounds
      },

      render: function() {
        ctx.fillStyle = '#000';
        ctx.fillRect(this.x, this.y, this.width, this.height);

        if (this.UP_DOWN)
          this.playerBat.y -= 5;

        else if (this.DOWN_DOWN)
          this.playerBat.y += 5;
      }
    };

The events are firing, the problem is that you're adding them on each update. What you'll want to do it take the callbacks and the addEventListeners outside in a method such as addEvents, which should be called ONCE during initialization. Currently the huge amount of event handlers being triggered kills the page.

    function addEvents() {

      window.addEventListener('keydown', onKeyDown, false);
      window.addEventListener('keyup', onKeyUp, false);

      var key = {
        UP: 38,
        DOWN: 40
      };

      function onKeyDown(e) {
        if (e.keyCode == key.UP) {
          playerPaddle.UP_DOWN = true;
        }

        if (e.keyCode == key.DOWN) {
          playerPaddle.DOWN_DOWN = true;
      }
    }

    function onKeyUp(e) {
      if (e.keyCode == key.UP) {
        playerPaddle.UP_DOWN = false;
      }

      if (e.keyCode == 40) {
        playerPaddle.DOWN_DOWN = key.DOWN;
      }
    }
}

After reviewing it further there are some other problems. First of all, the logic for actually changing the X and Y of the paddle should be within the update method (since that's what's usually used to change object properties), while the render method should simply draw the shapes and images using the object's updated properties.

Second, you're trying to access this.playerBat.y within the render method, however 'this' actually IS the playerBat. So in order to properly target the 'y' property you'd need to write this.y instead.

I also noticed that you've got a key map, with UP and DOWN keycodes defined, but don't actually use it, instead you use numbers. Maybe something you were planning on doing?

I reimplemented the code you have provided and added a init function to playerBat that attaches the event listeners for keydown and keyup events. I just kept the relevant bits and implemented objects as functions, but the concept should still be the applicable.

The callback function passed into addEventListener needs to bind this , otherwise the this value inside the callback ( this.UP_DOWN and this.DOWN_DOWN ) won't be the same as the this value in the enclosing scope; the one value you intended.

 <canvas id='canvas' style="background:#839496">Your browser doesn't support The HTML5 Canvas</canvas> <script> var canvas = document.getElementById('canvas'); canvas.width = window.innerWidth-20; canvas.height = window.innerHeight-20; var ctx = canvas.getContext('2d'); var Canvas_W = Math.floor(canvas.width); var Canvas_H = Math.floor(canvas.height); /* * Define a Player object. */ function PlayerBat(){ this.x = null; this.y = null; this.width = 20; this.height = Canvas_H/3; this.UP_DOWN = false; this.DOWN_DOWN = false; this.init = function() { console.log('init'); // MUST bind `this`! window.addEventListener('keydown', function(e){ console.log('keydown'); if (e.keyCode == 38) this.UP_DOWN = true; else if (e.keyCode == 40) this.DOWN_DOWN = true; }.bind(this), false); // MUST bind `this`! window.addEventListener('keyup', function(e){ console.log('keyUp') if (e.keyCode == 38) this.UP_DOWN = false; else if (e.keyCode == 40) this.DOWN_DOWN = false; }.bind(this), false); }; this.update = function() { var key = {UP: 38, DOWN: 40}; this.y = Math.max(Math.min(this.y, Canvas_H - this.height), 0); }; this.render = function() { // Clear the canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Redraw paddle ctx.fillStyle = '#00F'; ctx.fillRect(this.x, this.y, this.width, this.height); this.y = (this.UP_DOWN) ? this.y - 5 : ((this.DOWN_DOWN) ? this.y + 5 : this.y ); }; } function GameRunner(){ // Create instance of player var playerBat = new PlayerBat(); playerBat.init(); // Execute upon instantiation of GameRunner (function () { playerBat.x = playerBat.width; playerBat.y = (Canvas_H - playerBat.height) / 2; })(); function step() { playerBat.update(); playerBat.render(); requestAnimationFrame(step); } // Public method. Start animation loop this.start = function(){ requestAnimationFrame(step); } } // Create GameRunner instance var game = new GameRunner(); // Start game game.start(); </script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM