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

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

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

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


当前回答

    $(document).ready(function () {
        // using ascii 17 for ctrl, 18 for alt and 83 for "S"
        // ctr+alt+S
        var map = { 17: false, 18: false, 83: false };
        $(document).keyup(function (e) {
            if (e.keyCode in map) {
                map[e.keyCode] = true;
                if (map[17] && map[18] && map[83]) {
                    // Write your own code here, what  you want to do
                    map[17] = false;
                    map[18] = false;
                    map[83] = false;
                }
            }
            else {
                // if u press any other key apart from that "map" will reset.
                map[17] = false;
                map[18] = false;
                map[83] = false;
            }
        });

    });

其他回答

您应该使用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中工作时,这个概念也同样有效。

如果你想找到任何按键事件与控制键,你可以这样做

onkeypress = (e) =>{
console.log(e);
if(e.ctrlKey && e.code == "KeyZ"){
    document.write("do somthing")
} }

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

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);

对于任何使用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内的作用域变量被重置,我们不希望这样。

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

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+事件注册)。

请回复这是否有帮助。