We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I am controlling a sprite with arrow keys and having it pick-up/put-down with the ENTER/RETURN key but find the response somewhat erratic. Sometimes key presses are missed and other times two strokes may register, even with a quick tap of the key.
So when the ENTER key is tapped, he might pick something up, not pick it up, or pick it up and put it straight back down.
Here's a snippet of the function call...
this.dir = checkKeys();
and here's the function...
function checkKeys() {;
if (keyIsDown(LEFT_ARROW)) {
dir = "left";
} else if (keyIsDown(RIGHT_ARROW)) {
dir = "right";
} else if (keyIsDown(UP_ARROW)) {
dir = "up";
} else if (keyIsDown(DOWN_ARROW)) {
dir = "down";
} else if (keyIsDown(13)) {
mainSprite.pickUp();
} else {
dir = "standing";
}
return dir;
}
this.dir is then passed through a switch to assign moves, actions, animations, etc...
Would I be better off using a built in function like keyPressed() rather than calling a function and looking for a pressed key? Either way, is there a way to always capture the first keypress in the buffer and to empty the buffer if needed (for when I want a "tap" but not a "hold")?
Hmm, I've just noticed I'm returning dir except when the ENTER key is pressed in which case I call another function within the object. Could this cause glitches? Maybe I should give dir a value here and call the function in the switch?
Answers
Use keyPressed() and keyReleased(). With both, you can track if things are held down or not (consider storing the value of millis() when a key is pressed, when released you can compare to the current millis() to determine how long the press was). You might also be interested in keyTyped().
The problems you are seeing all stem from the fact that your key checking code happens every frame, while the built-in functions happen once per key event.
Thanks. I think I tried keyPressed() very early on but I was probably not using it correctly. I'll take another look.
I am counting millis with this one (in the .pickUp() function) but it clearly isn't working as I'd expected. It uses up some time, but doesn't solve the erratic problem. Maybe I'll have more luck with the built-in functions..
Javascript is new to me. I'm more used to procedural languages (QBASIC) where the keyboard buffer could be emptied before being rechecked, to prevent multiple registers. I guess keyReleased() might provide something similar.
I did a quick implementation of keyPressed() and keyReleased() but it's not quite there.
I commented-out the checkKeys() function and copied all the code (except "return dir") into keyPressed() and it basically works. The ENTER keys is much more responsive.
But if I press LEFT he keeps running left after the key is released. So, I put
dir="standing"
in keyReleased() and this stops him running, as expected.But, if I mash LEFT-RIGHT keys, he stops moving after the first release and then doesn't move again unless I pause. He should instantly turn back and forth with no pause but keyReleased seems to prevent fast key strokes.
I'll keep looking and see if I'm messing up elsewhere, but I could do with seeing these functions in action together as I never seem to get them right.
EDIT: I think what happens when keys are mashed is that the second key is pressed just before the first key is released - and keyPressed is only called once per press. Therefore keyReleased() for the first key is the latest event and its result appears to override the result from the second key which is now pressed but no longer registering as a key press. I might try keyTyped but I suspect I'll get the same result. (EDIT: KeyTyped doesn't register arrow keys. Sigh).
It's in Java syntax but here's some example using keyPressed() + keyReleased():
http://studio.SketchPad.cc/sp/pad/view/ro.91tcpPtI9LrXp/latest
Although keyIsDown() shoulda worked too:
http://p5js.org/reference/#/p5/keyIsDown
Thanks GoTo. Some of that makes sense so I'll give it some more attention and see what I can get to work.
It's not too bad using keyPressed() with keyReleased(), it's just a matter of not pressing two keys at once, which is fine for this purpose. It's working much better than it was before and I think I may be able to streamline it a little more.
I will also take another look at keyIsDown() since that appears to be the recommended method for this sort of thing (I'm avoiding p5.play for now as I want to learn stuff the hard way). I may have implemented it poorly.
keyIsDown() was indeed meant to replace keyPressed() + keyReleased() combo inside draw(). 8-X
But remember by default draw() is continuously called back at about 60 FPS! L-)