save keydown in array and executes - javascript

im creating a simple 2d game, and I want save the keydown keys into array, and execute them inisde a loop, so the user can hold a key and make it look like the chartater is moving non stop.
i got a setInterval function that act like a game Timer, and it just loop it self all the time. i added a listener and an array to hold the key.
I checked the keys inside the array and it look fine but, the functions moveRight and moveLeft are not working for some reson.
here is the code:
this.keysPressed = new Array();
InitGameLoop: function () {
var that = this;
setInterval(function () {
$(document).keydown(function (e) {
var key = e.which;
that.keysPressed.push(key);
for (var i = 0; i < that.keysPressed.length; i++) {
if (that.keysPressed[i] == 38) {
that.moveRight(worldWidth, 10);
}
else if (that.keysPressed[i] == 37) {
that.moveLeft(10);
}
log(that.keysPressed, that.yPos);
that.keysPressed.pop();
}
});
}, 60);
my questions are:
what am i doing worng?
is this a good idea? (if not, please feel free to recommend me about another :) )
(sorry for my english)

Registering an eventhandler inside setInterval is always wrong. In your case, every 60 milliseconds you are creating an additional listener, and when you press a key, all of your listeners will fire. Also there is absolutely no need to store them in an array. Just register the listener once, and it will fire each time a key is pressed. If more than one keys are pressed, the listener will fire for each key individually.
$(document).keydown(function (e) {
var key = e.which;
console.log(key);
// call your according functions here
switch (key){
case 37: // moving left
// do stuff
// set a flag to indicate that you are moving left
moveleft = true;
break;
case 39: // moving right
// do stuff
// set a flag to indicate that you are moving right
moveright = true;
break;
}
});
Since you are catching the keydown, you should set flags. This way you can track which keys are pressed currently. On keyup, you are resetting these flags again (need another eventhandler for that).

Instead of storing the pressed keys in an array, make each key code activate a related var in a 'movement' array. e.g. when left is pressed, movement['left']=1. Use keyup to set it back to 0.
Have your loop check the array for each possible movement, and trigger the related functions in corelance to the active movements at that given moment.

Related

How To Detect Two Characters (Keys) Pressed At The Same TIme

An important distinction is that it is easier to know if cntrl and z are pressed at the same time, but not as straight forward to detect if z and x are pressed at the same time. What is the best way to go about detecting when multiple characters are pressed at the same time?
This example uses event listeners to keep track of an object which contains all keys currently being pressed.
We can use this object to check if certain keys are pressed. This means that we can detect as many simultaneous key presses as a user's keyboard will allow.
Importantly it will let you detect when multiple characters are pressed at the same time.
const keysPressed = {};
document.addEventListener('keydown', (event) => {
if (!event.repeat)
keysPressed[event.key] = true;
//You can also include event.repeat as a condition in your cases if you wish an event to only occur once each trigger.
//You can also include Object.keys(keysPressed).length === 2 (for example) if you only wish the case to be valid if just two keys are pressed.
//Finally, instead of event.key === 'x' you can write keysPressed['x']. This would replace both non-default cases in the example. The result is that the event will continue firing if another key is pressed.
switch (true) { //You use true here because we are using logic to determine each case
case event.key === 'x' && keysPressed['z']:
case event.key === 'z' && keysPressed['x']:
console.log('Z and X pressed!');
break;
default:
break;
}
});
document.addEventListener('keyup', (event) => {
if (!event.repeat)
delete keysPressed[event.key];
});
I'm simply using an array as storage for all keys that are pressed. This array is cleaned to an empty state when keys are released.
In keydown event listener, you can hook the function with logic that you will want to implement. Read keys array to check all currently pressed keys.
const keys = []
document.addEventListener('keydown', e => {
!event.repeat && keys.push(e.key)
doSomethingWithKeys(keys)
})
document.addEventListener('keyup', e => {
keys.splice(0, keys.length)
})
function doSomethingWithKeys(keys) {
console.log('keys pressed:', keys.join('+'))
}

Trying to make a keyup used for 2 functions based on a timer

There is a button linked to a machine that sends a keypress to this app
Sometimes the button will "double tap" the key combination (Double shift + S)
Tried some of the responses over here: "How to trap double key press in javascript?"
as it seems along the lines of what I need but can't seem to get any to work
function myFunction(xml) {
// Start on keypress
document.addEventListener('keyup', function(e) {
if (e.keyCode == 83 && e.shiftKey)
// Set a baseline for first keypress to compare later
var lastKeypressTime = 0;
// Code to run after initial keypress here
// Basically a bunch of TTS reading from XML until either it finishes, or a button is pressed for a reload
// I think this is kind of along the lines of what I'm after but can't quite implement it properly
// Detect the keypress
document.addEventListener('keyup', function(e) {
if (e.keyCode == 83 && e.shiftKey)
// Set time of keypress to compare
var thisKeypressTime = new Date();
// if time between first keypress is greater than 2 seconds, let the page reload
if (thisKeypressTime - lastKeypressTime >= 2000)
window.location.reload();
else
// Otherwise, ignore all keypresses until the 2 seconds (at least) has passed before the button press works again
})
})
}
Due to the button being... imperfect.. When it registers a single press as a double press, the page is reloaded instantly
Basically needing either the first keypress that "starts" the TTS to never register a faulty double press, or have any consecutive keypress ignored entirely until after a certain period has passed or something to that extent
Any guidance or alternatives to what I'm trying to accomplish would be greatly appreciated :)
const delta = 1500;
let lastPress = 0;
function handleKeyPress(event) {
let currentPress = new Date();
if (event.key === "S" && event.shiftKey) {
if (currentPress - lastPress <= delta) {
alert("Shift + s");
currentPress = 0;
}
lastPress = currentPress;
}
}
document.addEventListener("keyup", handleKeyPress);
This is a snippet that works, you have to define the lastPress variable outside your function, and I don't understand why you're trying to register two listeners for the keyup event. Once that you've defined your listener handler, it will be called every time the event that you're listening on is fired; this is why you have to save the lastPress and the currentPress times.
P.S.
Obviously instead of alert something on the double keypress you can run your own function.

Phaser - On key release?

Instead of detecting when a key is down, how do I detect if a key is released?
One option is to use onUpCallback. For example, in your create function add something like the following:
game.input.keyboard.onUpCallback = function (e) {
// These can be checked against Phaser.Keyboard.UP, for example.
console.log(e.keyCode);
};
I suppose you could also store whether the key is down in your update function, and then check on each iteration whether it's up, if you wanted to keep track of the amount of time the key were pressed down.
I'm not sure what sort of performance issues you would run into though, so I would probably start with onUpCallback.
Set a flag when the key is pressed. In the update loop check if the flag is set but the key is no longer down:
//... somewhere
var downFlag = false;
//... in update
if(yourkey.isDown){
downFlag = true;
}else{
if(downFlag){
downFlag = false;
//do something
}
}
..but start with what James says

Javascript on key press trigger only once

I don't know why this appears to be so difficult to figure out. I want to be able to execute code when a key is pressed and held but only once. Instead when I use onkeypress or onkeydown the function that I bound gets executed repeatedly which is not what I want. How can I have the handler be executed just once when the key is held down?
Note: I don't want to embed logic into the function that will limit its execution, I want it not to be firing the event more than once no matter how long I hold the key.
EDIT I
Here is the demo and the code
HTML
<div id="counter">0</div>
JS
var counter = 0,
div = document.getElementById('counter');
document.body.onkeypress = function(){
div.innerHTML = counter++;
}
Notice how when you press and hold any key the counter keeps going, I want it to count just once no matter how long I hold the key, and keep in mind the notice from above.
EDIT II
Sorry forgot to mention removing the listener is not acceptable, I need to increase the counter by 1 every time a key is pressed but no matter how long it's held.
You do have to use logic to avoid repetitive events on a key being pressed, because there's no specific and compatible event for key being just pressed.
More specifically, the easiest solution is to store a boolean, setting it true on key up, false on key down (after having done your action), and ignoring the key down event while it's false:
(function(){
var shouldHandleKeyDown = true;
document.onkeydown = function(){
if (!shouldHandleKeyDown) return;
shouldHandleKeyDown = false;
// HANDLE KEY DOWN HERE
}
document.onkeyup = function(){
shouldHandleKeyDown = true;
}
})();
Demonstration
EDIT for 2019
Now that IE is dead, you can also use the event.repeat property, which is true when the event is a repetition.
The easiest way to handle this is by using the repeat property in the event:
// I'd recommend using addEventListener instead, but
// this is as close to the original code as possible
document.body.onkeypress = function (event) {
if (!event.repeat) {
div.innerHTML = counter++;
}
}
event.repeat is false for the very first event, and true for repeated events (the ones that are fired when you hold down a key).
Another option is to use keyup, which is always only used once, since you can't "hold up" a key, so it's never repeated (but keyup is a bad choice for e.g. buttons, because it can break keyboard navigation compared to keypress).
JSFiddle: http://jsfiddle.net/ts7w58od/
1. Bind listener
2. Unbind when event is fire.
var element = document.getElementById('target'),
once = function () {
console.log('once');
element.removeEventListener('keypress', once);
};
element.addEventListener('keypress', once, false);
This is a modified version of Denys Séguret answer
let shouldHandleKeyDown = true;
let n = 0;
document.addEventListener('keydown', function() {
if (!shouldHandleKeyDown) return;
shouldHandleKeyDown = false;
document.getElementById('counter').innerHTML = ++n;
});
document.addEventListener('keyup', function () {
shouldHandleKeyDown = true;
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Counter</title>
</head>
<body>
Counter : <span id=counter>0</span>
</body>
</html>

Determining if key is pressed down in Javascript

I'm writing a platform game for my university project using the canvas element and Javascript. I'm well on my way, but I'm stuck at how to see if a certain key is being pressed in my players update loop.
I was thinking like this:
if(d) {
// move player right
} else if(a) {
// move player left
} else if(w) {
// move player up
} else if(s) {
// move player down
}
That's psudocode, obviously. The only resources to key presses in Javascript that I can find are events, nothing to see if a key is being pressed at a certain point.
Can anyone shed some light on this?
Setup 4 boolean variables if key is up or down. On keydown set it to true, on keyup set it to false. Than you can do if(key_d == true) { // key d is pressed }
That's the best way to do it. Its not "hacky", add event listeners to handle key presses.
I don't think you can get around using keydown, keyup, or keypress for determining which keys are pressed. However, instead of running this code within one of those event handlers, you could set and unset some global flag within them. Then, when this code runs (I'm assuming it'll be on some kind of interval?), it could check for the flag.
You need an event listener.
//function foo, returns keypress
function foo(e){
var evt=(e)?e:(window.event)?window.event:null;
if(evt){
var key=(evt.charCode)?evt.charCode:
((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
return key;
}
//set event listener
//you could also attach this to your canvas, but that will require tricks
//to make the canvas focusable
document.addEventListener('keydown', foo);

Categories

Resources