【问题标题】:JS holding down a key has a delayJS按住一个键有延迟
【发布时间】:2018-03-20 21:03:13
【问题描述】:

我正在学习 JavaScript,并且正在尝试编写一个小游戏。 我希望我的游戏中的某些东西在我按住一个键时始终如一地移动。 到目前为止,这是我想出的:

document.onkeydown = onKeyDownListener;

function onKeyDownListener(evt) {
    var keyCode = evt.which || evt.keyCode;
    if(keyCode == 37) {
        move();
    }
}

我的问题是,当我按下键 move 被调用一次时,然后会有一个暂停,之后暂停 move 会按照我的意图重复调用。它去 像这样:m......mmmmmmmmm 当'm'代表移动和'。'是停顿。 有没有办法摆脱暂停?

这是发生的事情的 GIF:

【问题讨论】:

  • 您的键盘就是这样工作的。按键重复不会立即开始;否则打字会很烦人。
  • 你说得对,这种行为确实是有目的的,我非常清楚这一点。但正如我解释的那样,我不希望这种行为发生在我的情况下。

标签: javascript html html5-canvas


【解决方案1】:

我很确定你有这个问题,因为你不依赖游戏循环来运行你的游戏。如果你是,你就不会遇到这个问题,因为每个间隔的游戏循环都会检查按键是否被按下。您的网络应用只会在每次按键发生时做出反应。

我强烈建议您阅读本教程:

W3 HTML 游戏 - 游戏控制器

https://www.w3schools.com/graphics/game_movement.asp

阅读“键盘作为控制器”部分。本例中的“setInterval”方法引发了游戏循环。

我用它作为自己编写游戏代码的参考。

这是来自 W3 教程的代码。它还继续教授碰撞检测。

var myGameArea = {
    canvas : document.createElement("canvas"),
    start : function() {
        this.canvas.width = 480;
        this.canvas.height = 270;
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, document.body.childNodes[0]);
        this.interval = setInterval(updateGameArea, 20);
        window.addEventListener('keydown', function (e) {
            myGameArea.keys = (myGameArea.keys || []);
            myGameArea.keys[e.keyCode] = true;
        })
        window.addEventListener('keyup', function (e) {
            myGameArea.keys[e.keyCode] = false; 
        })
    }, 
    clear : function(){
        this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    }
}

 function updateGameArea() {
    myGameArea.clear();
    myGamePiece.speedX = 0;
    myGamePiece.speedY = 0; 
    if (myGameArea.keys && myGameArea.keys[37]) {myGamePiece.speedX = -1; }
    if (myGameArea.keys && myGameArea.keys[39]) {myGamePiece.speedX = 1; }
    if (myGameArea.keys && myGameArea.keys[38]) {myGamePiece.speedY = -1; }
    if (myGameArea.keys && myGameArea.keys[40]) {myGamePiece.speedY = 1; }
    myGamePiece.newPos(); 
    myGamePiece.update();
}

【讨论】:

  • 我在 Udemy udemy.com/how-to-program-games 上遵循了这个教程,现在我想在游戏中构建更多功能。我确实使用游戏循环。如果您愿意,可以在这里查看完整代码:jpst.it/1cBSK 我尝试了@Gorgamite 的答案,在添加了一些惯性/加速度之后,它现在可以正常工作了。无论如何,谢谢您的回答和链接:)
  • @Yannic 看起来您最初并没有在 keyup 和 keydown 上设置“arrowLeftDown”布尔值,而不是在按下键时简单地调用“move()”来解决问题。
【解决方案2】:

你可以试试这个:

document.onkeydown = onKeyDownListener;
var keyDown = false;
function onKeyDownListener(evt) {
   if(evt.keyCode == 37) {
keyDown = true;
   }
}

document.onkeyup = function(evt){
 if(evt.keyCode == 37) {
keyDown = false;
   }
}

setInterval(function(){
if(keyDown){
player.x--;
}
},20)

我知道这并不理想,但我最好的猜测是按键检测存在问题。这样,只要您按住该键,它就会移动,直到您松开该键为止。

【讨论】:

  • 这符合我必须回应的想法。
  • 它可能不会重复开始,但它不会启动keydown,注册一个按键,然后在短暂的暂停后恢复?
  • @Gorgamite 是的,对不起,我没有正确阅读代码;这可能会奏效,尽管当间隔计时器恰好在“keyup”之前触发 right 时,它可能会捕获一些不真实的重复。出于 OP 的目的,可能没问题。
  • 是的....好吧,考虑到它只会错误地持续 1/50 秒,我认为抵押品很少
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多