我试图开发一个JavaScript游戏引擎,我遇到了这个问题:

当我按空格键时,角色会跳跃。 当我按下→角色向右移动。

问题是,当我按右键,然后按空格键时,角色会跳跃,然后停止移动。

我使用keydown函数来按下键。如何检查是否同时按下了多个键?


当前回答

谁需要完整的示例代码。左+右补充道

var keyPressed = {};
document.addEventListener('keydown', function(e) {

   keyPressed[e.key + e.location] = true;

    if(keyPressed.Shift1 == true && keyPressed.Control1 == true){
        // Left shift+CONTROL pressed!
        keyPressed = {}; // reset key map
    }
    if(keyPressed.Shift2 == true && keyPressed.Control2 == true){
        // Right shift+CONTROL pressed!
        keyPressed = {};
    }

}, false);

document.addEventListener('keyup', function(e) {
   keyPressed[e.key + e.location] = false;

   keyPressed = {};
}, false);

其他回答

如果有人需要简单的解决方案。

let keys = [];
document.addEventListener("keydown", (e) => {
  keys.push(e.key);
  if (keys.includes("Control") && keys.includes("o")) {
    console.log("open");
  }

  if (keys.includes("Control") && keys.includes("s")) {
    console.log("save");
  }
});

// clear the keys array
document.addEventListener("keyup", () => {
  keys = [];
});

对于任何使用React的人,这里是我的解决方案:

import { useEffect, useState } from "react";
import Backdrop from '@mui/material/Backdrop';

export const Example = () => {
  const [backdropOpen, setBackdropOpen] = useState(false);

  useEffect(() => {
    // Keys that need to be pressed at the same time in order for
    // the 'backdropOpen' variable to be 'true'
    const keysArr = ['ControlLeft', 'ShiftLeft', 'AltLeft'];
    const keysMap = {};
    let backdropOpenLocal = false;

    const keydownEvent = 'keydown';
    const keyupEvent = 'keyup';

    const checkKeys = () => {
      const keysArePressed = keysArr.every((value) => keysMap[value] === keydownEvent);
      if (keysArePressed !== backdropOpenLocal) {
        backdropOpenLocal = keysArePressed;
        setBackdropOpen(keysArePressed);
      }
    }

    const handleKeyDown = (event) => {
      const keyCode = event.code;
      if (keysArr.includes(keyCode) && keysMap[keyCode] !== keydownEvent) {
        keysMap[keyCode] = keydownEvent;
      }
      checkKeys();
    }

    const handleKeyUp = (event) => {
      const keyCode = event.code;
      if (keysArr.includes(keyCode) && keysMap[keyCode] !== keyupEvent) {
        keysMap[keyCode] = keyupEvent;
      }
      checkKeys();
    }

    document.addEventListener('keydown', handleKeyDown);
    document.addEventListener('keyup', handleKeyUp);

    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      document.removeEventListener('keyup', handleKeyUp);
    }
  }, []);

  return (
    <React.Fragmemnt>
      <div>
        <Backdrop
          open={backdropOpen}
        >
          <span>
            It worked!
          </span>
        </Backdrop>
      </div>
    </React.Fragmemnt>
  );
}

请记住,我们需要在useEffect函数中使用backdropOpenLocal而不是backdropOpen,因为我们只想更新局部作用域变量并保持作用域的状态。

如果我们更新Example组件的状态并尝试访问backdropOpen,我们将得到与之前相同的值,除非我们在useEffect的依赖数组中传递backdropOpen;这将导致useEffect内的作用域变量被重置,我们不希望这样。

这是布雷登斯答案的一个实现。

Var键= {} handleKeyPress(evt) { let {keyCode, type} = evt ||事件;//处理IE let isKeyDown = (type == 'keydown'); keys[keyCode] = isKeyDown; // test: enter键被按下,shift键没有被按下 if(isKeyDown && keys[13] && !keys[16]){ Console.log('用户按下enter没有shift') } }; 窗口。addEventListener(“弹起”,handleKeyPress); 窗口。addEventListener(“keydown”,handleKeyPress);

我会试着在按键时添加一个按键事件处理程序。例句:

window.onkeydown = function() {
    // evaluate key and call respective handler
    window.onkeypress = function() {
       // evaluate key and call respective handler
    }
}

window.onkeyup = function() {
    window.onkeypress = void(0) ;
}

这只是为了说明一个模式;这里我就不详细介绍了(尤其是浏览器特定的level2+事件注册)。

请回复这是否有帮助。

您应该使用keydown事件来跟踪按下的键,并且应该使用keyup事件来跟踪何时释放键。

请看这个例子:http://jsfiddle.net/vor0nwe/mkHsU/

(更新:我在这里复制代码,以防jsfiddle.net崩溃:) HTML:

<ul id="log">
    <li>List of keys:</li>
</ul>

...和Javascript(使用jQuery):

var log = $('#log')[0],
    pressedKeys = [];

$(document.body).keydown(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
        li = log.appendChild(document.createElement('li'));
        pressedKeys[evt.keyCode] = li;
    }
    $(li).text('Down: ' + evt.keyCode);
    $(li).removeClass('key-up');
});

$(document.body).keyup(function (evt) {
    var li = pressedKeys[evt.keyCode];
    if (!li) {
       li = log.appendChild(document.createElement('li'));
    }
    $(li).text('Up: ' + evt.keyCode);
    $(li).addClass('key-up');
});

在这个例子中,我使用一个数组来跟踪哪些键被按下。在实际应用程序中,您可能希望在释放每个元素的关联键之后删除它们。

注意,虽然我在这个例子中使用了jQuery使事情变得简单,但在“原始”Javascript中工作时,这个概念也同样有效。