【问题标题】:Keyboard input pause [duplicate]键盘输入暂停[重复]
【发布时间】:2019-04-16 19:54:28
【问题描述】:

我做了一个非常基本的演示,你按下箭头键,方块就会朝那个方向移动。一个问题:当我第一次按键时,方块移动了一点,暂停,然后继续移动。如何摆脱或解决暂停?

代码:

    var canvas = document.getElementById("canvas")
    var ctx = canvas.getContext('2d');
    var p1 = document.getElementById("p1");
    var keys = [];
    var x = 25
    var y = 25
    
    document.addEventListener("keydown", function(e) {
      keys[e.keyCode] = true;
      update();
    });
    
    document.addEventListener("keyup", function(e) {
      keys[e.keyCode] = false;
      update();
    });
    
    function update() {
      ctx.clearRect(0, 0, 400, 400)
      
      if(keys[40] == true) {
        y += 5
      }
      
      if(keys[38] == true) {
        y -= 5
      }
      
      if(keys[39] == true) {
        x += 5
      }
      
      if(keys[37] == true) {
        x -= 5
      }
      
      ctx.fillRect(x, y, 100, 100)
      
      console.log(keys);
    
      p1.innerText = "";
    
      for (i = 0; i < keys.length; i++) {
        if (keys[i]) {
          p1.innerText += i + " | ";
        }
      }
    }
    <canvas id='canvas' width='400' height='400'></canvas>
    <p id='p1'>testing</p>

【问题讨论】:

标签: javascript input


【解决方案1】:

这是因为keydown 事件是continuously fired at different intervals in different browsers

与其依赖浏览器不时地发送keydown,不如让你自己的更新循环在60fps运行,使用requestAnimationFrame,并且每一帧都根据按下的键移动框。

var canvas = document.getElementById("canvas")
var ctx = canvas.getContext('2d');
var p1 = document.getElementById("p1");
var keys = [];
var x = 25
var y = 25

document.addEventListener("keydown", function(e) {  
  e.preventDefault(); // make sure this doesn't scroll the window
  keys[e.keyCode] = true;
});

document.addEventListener("keyup", function(e) {
  keys[e.keyCode] = false;
});

function update() {
  //  Tell the browser to run again update when it is "free",
  // preferably at 60fps (actually your monitor's refresh rate)
  requestAnimationFrame(update);

  ctx.clearRect(0, 0, 400, 400)

  if(keys[40] == true) {
    y += 5
  }

  if(keys[38] == true) {
    y -= 5
  }

  if(keys[39] == true) {
    x += 5
  }

  if(keys[37] == true) {
    x -= 5
  }

  ctx.fillRect(x, y, 100, 100)

  p1.innerText = "";

  for (i = 0; i < keys.length; i++) {
    if (keys[i]) {
      p1.innerText += i + " | ";
    }
  }
}
update(); // Start running the loop at 60fps
<canvas id='canvas' width='400' height='400'></canvas>
<p id='p1'>testing</p>

请注意,框在给定时间内移动的距离取决于您的帧速率,因此如果浏览器无法跟上60fps 并且只有在30fps 处运行,update 只会被调用一半,所以盒子只会移动它在60fps 处移动距离的一半。要了解有关动画和游戏更新循环的更多信息,我建议阅读此fix your timestep article

【讨论】:

  • 我也认为 Event.preventDefault() 应该在浏览器环境中使用 - 使用箭头时。并且还应考虑对角线运动补偿。
  • @RokoC.Buljan 感谢您的建议,我已将其添加到我的答案中。
  • 我试过这段代码,但由于某种原因,它不能在 Codepen 中运行。我需要添加任何东西才能使其运行吗?
  • @ARCS2016 如果您按上面的“运行代码 sn-p”,您应该会看到它正在工作。
  • 是的,nvm 现在可以工作了。我不知道为什么以前没有。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-04
相关资源
最近更新 更多