使用另一个键

时间:2016-10-07 17:52:49

标签: javascript jquery keyevent key-events

在我的游戏中,我使用事件监听器keyupkeydown来跟踪按下哪些键(this.input是对下面Input函数的引用):< / p>

$(document.body).on('keydown', this.input.keyPress.bind(this.input));
$(document.body).on('keyup', this.input.keyPress.bind(this.input));

一切都按预期工作,直到我一次按下2个键。左键将玩家向左移动,shift键发射武器。另外,他们工作正常。然而,如果同时按下并保持两者,则玩家会两次射击。

以下是我用来处理输入的代码(为简洁起见,删除了其他关键事件)

shootSpecial只应调用一次,因为keyMap.shift仅在truekeydown。触发keyup后,会将其设置为falsekeyMap[key] = e.type === 'keydown';

var Input = function () {
  var keyMap = {};

  this.handleKeyPress = function () {
    if (keyMap.arrowleft === true) {
      game.player.moving.left = true;
    } else if (keyMap.shift === true) {
      game.player.shootSpecial();
    }
  };

  this.keyPress = function (e) {
    var key = e.key.toLowerCase();
    if (key === ' ') {
      key = 'space';
    }
    keyMap[key] = e.type === 'keydown';
    console.log(key, keyMap[key]);
    this.handleKeyPress();
  };
};

离开转移console.log报告true keydownfalse keyup {} {1}}所以我不太清楚为什么会两次触发shootSpecial事件。

var keyMap = {};
var handleKeyPress = function () {
  if (keyMap.arrowleft === true) {
    console.log('left');
  } else if (keyMap.shift === true) {
    console.log('shift');  
  }
};

var keyPress = function (e) {
  var key = e.key.toLowerCase();
  keyMap[key] = e.type === 'keydown';
  if (document.getElementById(key))
    document.getElementById(key).innerText = e.type === 'keydown';
  
  handleKeyPress();
}

document.addEventListener('keydown', keyPress);
document.addEventListener('keyup', keyPress);
LEFT:<div id="arrowleft">false</div>
SHIFT:<div id="shift">false</div>

正如你可以看到的那样,一个事件会被调用两次。

2 个答案:

答案 0 :(得分:1)

您的问题是您使用相同的代码处理keydown和keyup,结果是在按下key2时释放key1与按key2具有相同的效果。

修复非常简单:在keyup事件中根本不调用handleKeyPress函数。

&#13;
&#13;
#!/usr/bin/env python
from csv import DictReader, DictWriter

data = '''A,B,C
1,2,3
4,5,6
6,7,8'''

reader = DictReader(data.split('\n'))

# You'll need your fieldnames first in a list to ensure order
fieldnames = ['A', 'C']
# We'll also use a set for efficient lookup
fieldnames_set = set(fieldnames)

with open('outfile.csv', 'w') as outfile:
    writer = DictWriter(outfile, fieldnames)
    writer.writeheader()
    for row in reader:
        # Use a dictionary comprehension to iterate over the key, value pairs
        # discarding those pairs whose key is not in the set
        filtered_row = dict(
            (k, v) for k, v in row.iteritems() if k in fieldnames_set
        )
        writer.writerow(filtered_row)
&#13;
var keyMap = {};
var handleKeyPress = function () {
  if (keyMap.arrowleft === true) {
    console.log('left');
  } else if (keyMap.shift === true) {
    console.log('shift');  
  }
};

var keyPress = function (e) {
  var key = e.key.toLowerCase();
  keyMap[key] = e.type === 'keydown';
  if (document.getElementById(key))
    document.getElementById(key).innerText = e.type === 'keydown';
  
  // Only call handleKeyPress if the key is pressed
  if (keyMap[key]) {
    handleKeyPress();
  }
}

document.addEventListener('keydown', keyPress);
document.addEventListener('keyup', keyPress);
&#13;
&#13;
&#13;

添加建议以回应OP的评论。你的问题是你的handleKeyPress()没有关于按下或按下按键的信息,也没有知道哪个按键被按下,只有哪些按键在被调用时才被按下。为了得到你的目标,我会做这样的事情:

&#13;
&#13;
LEFT:<div id="arrowleft">false</div>
SHIFT:<div id="shift">false</div>
&#13;
var keyPress = function (e) {
  var key = e.key.toLowerCase(),
      isKeyDown = e.type === "keydown",
      output = key + (isKeyDown ? "-down" : "-up") + ": ";
  
  switch (key) {
    case "shift":
      if (isKeyDown) {
        output += "pew pew";
      } else {
        output += "doing nothing"
      }
      break;
      
    case "arrowleft":
      output += "updating walking_left";
      document.getElementById("walking_left").innerText = isKeyDown;
      break;
      
    default:
      output += "doing nothing";
  }

  console.log(output);
};

document.addEventListener('keydown', keyPress);
document.addEventListener('keyup', keyPress);
&#13;
&#13;
&#13;

答案 1 :(得分:0)

如果按两个键,无论是否同时按下它们,都会触发两个事件。 keyup事件也是如此。所以总共 handleKeypress 函数被调用四次。

订单可能恰好是:

key        | event   | keyMap.arrowleft | keyMap.shift | effect
-----------+---------+------------------+--------------+----------
shift      | keydown |     false        |     true     | shoot
arrowleft  | keydown |     true         |     true     | moving.left=true
arrowleft  | keyup   |     false        |     true     | shoot
shift      | keyup   |     false        |     false    | nothing

所以在这种情况下你会拍两次。当然,情况并非总是如此,因为订单可能不同。

解决方案

将键作为参数传递给 handleKeyPress 函数,以确保只执行与该键对应的操作。

var Input = function () {
  var keyMap = {};

  this.handleKeyPress = function (key) {
    switch (key) {
    case 'arrowleft':
      game.player.moving.left = keyMap[key]; // also sets back to false
      break;
    case 'shift':
      if (keyMap.shift) game.player.shootSpecial();
      break;
    }
  };

  this.keyPress = function (e) {
    var key = e.key.toLowerCase();
    if (key === ' ') {
      key = 'space';
    }
    keyMap[key] = e.type === 'keydown';
    this.handleKeyPress(key); // pass key
  };
};