admin管理员组文章数量:1420086
Working on a small game using an HTML5 canvas, and javascript. And it's working quite nicely, apart from keyboard keys occasionally getting "stuck", ie. it'll register a keydown event, but sometimes it won't register the keyup event. This generally happens when hitting multiple keys at once, so it is in part a hardware or OS fault, but I'm hoping someone has ideas on how to work around this. The relevant parts of my code (written in coffeescript):
press = (direction) ->
switch direction
when 'W'
game.keys.W = true
when 'S'
game.keys.S = true
when 'A'
game.keys.A = true
when 'D'
game.keys.D = true
release = (direction) ->
switch direction
when 'W'
game.keys.W = false
when 'S'
game.keys.S = false
when 'A'
game.keys.A = false
when 'D'
game.keys.D = false
doKeyDown = (evt) ->
switch evt.keyCode
when 87 then press 'W'
when 83 then press 'S'
when 65 then press 'A'
when 68 then press 'D'
doKeyUp = (evt) ->
switch evt.keyCode
when 87 then release 'W'
when 83 then release 'S'
when 65 then release 'A'
when 68 then release 'D'
window.addEventListener('keydown', doKeyDown, false)
window.addEventListener('keyup', doKeyUp, false)
Basic stuff. It wouldn't be a problem if javascript wasn't entirely event-driven, but what can you do. My current idea for how to circumvent the problem would be to add a queue for keypresses, with a capacity for 2 or 3 keys, and when the limit is exceeded, the first key(s) in are removed and are switched to 'false'. Still, it seems weird to add an artificial limit like this, when it should be avoidable!
So, the question is, is there a straightforward way to ensuring key states are saved accurately, without having to resort to workarounds? Preferably something that works independently of the framerate of the game (should work equally well whether it's running at 1000 fps, or 3 fps).
Working on a small game using an HTML5 canvas, and javascript. And it's working quite nicely, apart from keyboard keys occasionally getting "stuck", ie. it'll register a keydown event, but sometimes it won't register the keyup event. This generally happens when hitting multiple keys at once, so it is in part a hardware or OS fault, but I'm hoping someone has ideas on how to work around this. The relevant parts of my code (written in coffeescript):
press = (direction) ->
switch direction
when 'W'
game.keys.W = true
when 'S'
game.keys.S = true
when 'A'
game.keys.A = true
when 'D'
game.keys.D = true
release = (direction) ->
switch direction
when 'W'
game.keys.W = false
when 'S'
game.keys.S = false
when 'A'
game.keys.A = false
when 'D'
game.keys.D = false
doKeyDown = (evt) ->
switch evt.keyCode
when 87 then press 'W'
when 83 then press 'S'
when 65 then press 'A'
when 68 then press 'D'
doKeyUp = (evt) ->
switch evt.keyCode
when 87 then release 'W'
when 83 then release 'S'
when 65 then release 'A'
when 68 then release 'D'
window.addEventListener('keydown', doKeyDown, false)
window.addEventListener('keyup', doKeyUp, false)
Basic stuff. It wouldn't be a problem if javascript wasn't entirely event-driven, but what can you do. My current idea for how to circumvent the problem would be to add a queue for keypresses, with a capacity for 2 or 3 keys, and when the limit is exceeded, the first key(s) in are removed and are switched to 'false'. Still, it seems weird to add an artificial limit like this, when it should be avoidable!
So, the question is, is there a straightforward way to ensuring key states are saved accurately, without having to resort to workarounds? Preferably something that works independently of the framerate of the game (should work equally well whether it's running at 1000 fps, or 3 fps).
Share Improve this question edited Jun 8, 2012 at 13:02 TJHeuvel 12.6k4 gold badges39 silver badges46 bronze badges asked Jun 8, 2012 at 13:00 FaultFault 4203 silver badges17 bronze badges 4-
Can't you write
game.keys[direction] = true
in coffeescript? It'd save some typing ... – Pointy Commented Jun 8, 2012 at 13:02 -
also
press String.fromCharCode(evt.keyCode)
– Pointy Commented Jun 8, 2012 at 13:03 - I could indeed! Thanks for pointing that out. Still new to javascript, or, well, scripting languages as a whole, so I end up missing a lot of the nice ways in which things can be optimized/condensed. – Fault Commented Jun 8, 2012 at 13:17
-
I've never heard of a work-around for this. If the events aren't being delivered after binding them to the
window
, then you're either right that it's an OS bug, or the window just doesn't have focus at the time ofkeyup
. The same issue can be observed even in native SDL applications. – bkconrad Commented Jun 8, 2012 at 13:28
4 Answers
Reset to default 3Since keydown
events fire rapidly, you could store a timestamp noting when the last time you heard the key was depressed:
when 'A'
game.keys.A = [true, +newDate()]
Then, run an interval function to check for keys that are still registered as depressed but have not sent a keydown
event for some duration (say, 1 second) and set them as released.
My above example might require you to refactor a lot of your code (since game.keys.A
is now an array instead of a boolean). Instead, you could hold the timestamps in their own object:
last_keydown_times = {};
...
when 'A'
game.keys.A = true
last_keydown_times['A'] = +new Date();
Have the interval function check the members of last_keydown_times
(perhaps in a for...in
loop) and check for expired values:
setInterval(function() {
var now = +new Date();
for(key in last_keydown_times) {
if(now - last_keydown_times[key] >= 1000) {
// run the release code for this key
}
}
}, 1000);
If this is happening on OSX, be aware that you simply don't get any keyup events while the cmd
key is held down.
AFAICT there is no solution to this problem. The only way to track which keys are currently down is through keyup/keydown events, and on a Mac the cmd key robs you of this information.
It's worth pointing out that having more keydown
events than keyup
events is actually expected behavior: When you hold a key down, the OS reports that as multiple keydown
s (one for each time that a character would be inserted in a normal text input, though this happens even under Mac OS 10.7 with its default key-holding behavior). You'll only get a keyup
when the key is physically released.
Of course, your code shouldn't be affected by this issue. So if you're really in a situation where game.keys.A
is true
well after you've released the A
key, you should report that as a bug in the browser(s) you're experiencing the problem in. I don't believe a workaround to be possible.
This is a mon issue with all but the more expensive keyboards.
As an example, try playing a game where you have the arrow keys to move and Space to fire. You'll find that pressing two arrows may result in you being unable to shoot.
Unfortunately there isn't anything you can do to fix this, because a lot of keyboards are different. What you should do is allow the user to customise their controls in case they encounter the problem, so they can change to a set of controls that doesn't have this issue.
本文标签: keyboardJavascript quotstuckquot keys (unregistered keyup event)Stack Overflow
版权声明:本文标题:keyboard - Javascript "stuck" keys (unregistered keyup event) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745328119a2653685.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论