当前位置: 首页 > 知识库问答 >
问题:

Javascript:限制keydown事件侦听器在被按住时调用函数的速度

丁雅逸
2023-03-14

我正在开发一款基于JavaScript的游戏,目前正在研究游戏角色的移动和动画。当玩家在击键事件期间按下控件 (WASD) 时,将对此进行控制。我遇到的问题是,当按下并按住这些键时,处理程序的调用速度太快,这使我的游戏角色/子画面看起来像是癫痫发作(因为它在精灵图像中循环得太快)。

我怎样才能限制调用角色运动/动画行为的速度?我的代码目前如下所示:

let canvas = document.getElementById('myCanvas');
ctx = canvas.getContext('2d');
let xPos = 10
let yPos = 10
document.addEventListener('keydown', movement)

function movement(e){
//Player Controls 
// horizontal and vertical movement
    if (e.keyCode === 87 ){
         ctx.clearRect(0,0, canvas.width, canvas.height);
         y=y-3;
         sY = 97
         runningMan();
    }
     if(e.keyCode === 83){
        ctx.clearRect(0,0, canvas.width, canvas.height);
        y=y+3;
        sY = 0
        runningMan();
    }
    if(e.keyCode === 65){
        ctx.clearRect(0,0, canvas.width, canvas.height);
        x=x-3;
        sY = 32
        runningMan();
    }
    if(e.keyCode === 68){
        ctx.clearRect(0,0, canvas.width, canvas.height);
        x=x+3;
        sY = 64
        runningMan();
    }
  
 
    // keeping the player inside the canvas
    xPos = Math.min(Math.max(x, 0+5), canvas.width-10);
    yPos = Math.min(Math.max(y, 0+5), canvas.height-10); 
}

//img,SX,SY,SW,SH,DX,DY,DW,DH)
let img = new Image();
img.src = 'runningGood.png'
let cycle = 0
let sY;
let sW = 30 
let sH = 32
let x = 0
let y = 0
let increase = 0
// setInterval(runningMan, 200);
function runningMan(){
    ctx.clearRect(0,0,sW+increase,sH+increase);
    ctx.drawImage(img,cycle*sW,sY,sW,sH,x,y,70,70)
    cycle = (cycle + 1) % 3;
  }
<!DOCTYPE html>
    <html lang='en'>
        <head>
            <meta charset='UTF-8'>
            <script src='project.js' defer></script>
            <title>1045 Project</title>
        </head>
        <body>
            <canvas id='myCanvas' width='750' height ='750' style='border: 2px solid black'></canvas>
        </body>
    </html>

共有1个答案

董弘新
2023-03-14

一个与当前代码集成并避免需要第三方库的解决方案是添加以下内容:

let canvas = document.getElementById('myCanvas');
ctx = canvas.getContext('2d');
let xPos = 10
let yPos = 10

/* Add: track state of current throttle timer */
let throttle;
/* Add: When keyup happens, just reset the throttle timer */
document.addEventListener('keyup', () => {
  if (throttle) {
    clearTimeout(throttle);
    throttle = null;
  }
})

document.addEventListener('keydown', movement)

function movement(e) {

  /* Add: only allow normal keypress processing if no throttle
  timer is currently active */
  if (!throttle) {

    //Player Controls 
    // horizontal and vertical movement
    if (e.keyCode === 87) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      y = y - 3;
      sY = 97
      runningMan();
    }
    if (e.keyCode === 83) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      y = y + 3;
      sY = 0
      runningMan();
    }
    if (e.keyCode === 65) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      x = x - 3;
      sY = 32
      runningMan();
    }
    if (e.keyCode === 68) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      x = x + 3;
      sY = 64
      runningMan();
    }


    // keeping the player inside the canvas
    xPos = Math.min(Math.max(x, 0 + 5), canvas.width - 10);
    yPos = Math.min(Math.max(y, 0 + 5), canvas.height - 10);


    /* Add: Start a "throttle" timer that prevents next keyboard processing
    until timer completed */
    throttle = setTimeout(() => {

      throttle = null;

    /* Your throttle interval - reduce/increase this number to suit you needs */
    }, 1000)
  }
}

//img,SX,SY,SW,SH,DX,DY,DW,DH)
let img = new Image();
img.src = 'https://via.placeholder.com/160'
let cycle = 0
let sY;
let sW = 30
let sH = 32
let x = 0
let y = 0
let increase = 0
// setInterval(runningMan, 200);
function runningMan() {
  ctx.clearRect(0, 0, sW + increase, sH + increase);
  ctx.drawImage(img, cycle * sW, sY, sW, sH, x, y, 70, 70)
  cycle = (cycle + 1) % 3;
}
html prettyprint-override"><!DOCTYPE html>
<html lang='en'>

<head>
  <meta charset='UTF-8'>
  <script src='project.js' defer></script>
  <title>1045 Project</title>
</head>

<body>
  <canvas id='myCanvas' width='750' height='750' style='border: 2px solid black'></canvas>
</body>

</html>
 类似资料:
  • 我遇到了一个奇怪的JavaScript问题。我正在开发一个使用键盘输入的HTML5画布游戏。游戏的双人模式需要按住键盘上最多6个键。 在我按住键盘上的4或5个键后,似乎停止调用“keyDown”事件。 我使用的代码如下: 控制台应该为我按下的每个键记录一个键代码。然而,它似乎只报告我按住的前4或5个键的密码。这导致了当两个玩家按下太多键时,我的游戏的双玩家版本的控件无法工作。 这是一个bug,是J

  • 在致力于提高渐进式web应用程序的性能时,我遇到了一个新功能,我发现很难理解这个概念。 什么是被动事件侦听器,在我们的项目中需要它吗?

  • 我目前正在尝试编写一些JavaScript来获取已单击的类的属性。我知道要正确地执行此操作,我应该使用事件监听器。我的代码如下: 我希望每次点击其中一个类时都有一个警告框来告诉我该属性,但不幸的是,这并不起作用。有人能帮忙吗?

  • 问题内容: 如何启用处理JPA回调的Hibernate事件侦听器? 当前,我正在将Hibernate 4与SessionFactory配置一起使用,但是当我保留一个对象时,JPA回调无法正常运行。 任何建议都是最欢迎的。 源代码 临时实体类: TempVal类: MainClass类: Hibernate配置: 程序输出 程序输出如下: 预期的输出将是: 问题答案: 这个问题基本上是一样的。 事实

  • 单击选择元素显示此警告: [违规]将非被动事件侦听器添加到滚动阻止“鼠标滚轮”事件。将事件处理程序标记为“被动”以使页面更加响应。 问题是,这也扩大了谷歌浏览器中HTML页面的高度。在Chrome版本59.0中测试。3071.86(官方版本)(64位)在firefox中不会出现这种情况。 简单代码:https://jsfiddle.net/gurigraphics/2399mnyb 如果自定义滚动

  • 问题内容: 我有一个带有模型和视图的Swing应用程序。在视图(GUI)中,有很多组件,每个组件都映射到模型对象的某些属性并显示其值。 现在,有一些UI组件会在UI中的值更改时自动触发某些模型属性的更新。这需要我在UI中重新加载完整的模型。这样,我进入了一个无限的更新循环,因为UI中的每个模型重新加载都会触发另一个模型重新加载。 我有一个指示加载过程的标志,在通过模型设置UI字段时,我想使用它来临