im creating a browser game and i have added keybinds so the player can use keys to move around the world.
If people use the buttons to move, these buttons are getting hidden for 5 seconds to allow an animation to end. Now i want to do this for the keybinds too.
For example: Player presses spacebar and a interval will run that lasts 5 seconds. Pressing space again will glitch out really bad running the same interval twice. So how do i disable a function for 5 seconds after it has been called so that it won't glitch out?
This is the code i use for the keys:
<script>
document.body.onkeyup = function(e){
if(e.keyCode == 32){
var cmd = "<?php echo $row['HEADING']; ?>";
if(cmd == "N") myMoveUp();
if(cmd == "E") myMoveRight();
if(cmd == "S") myMoveDown();
if(cmd == "W") myMoveLeft();
}
if(e.keyCode == 37){
ChangeHeadingKP("W");
}
if(e.keyCode == 38){
ChangeHeadingKP("N");
}
if(e.keyCode == 39){
ChangeHeadingKP("E");
}
if(e.keyCode == 40){
ChangeHeadingKP("S");
}
}
</script>
Any help would be appreciated.
I wouldn't rely on timing (say, 5 seconds) because when you change them, you'll have to review your code.
Instead I'd rely on toggling a flag by calling specific methods, like this:
keymanager.suspend();
// play animation, cutscene or whatever
keymanager.resume();
Those two functions are easy to define, along with the keymanager, as follows:
var keymanager = {
"active": true,
"suspend": () => {
keymanager.active = false;
},
"resume": () => {
keymanager.active = true;
}
};
All that remains is the key event handler bailing out when keys are deactivated:
document.body.onkeyup = function (e) {
if (!keymanager.active)
{
return; // do not process any keys
}
// rest of your code...
}
Related
I work on a simple game clone of pacman. The only thing i have a problem with is how to get input from the user via keyboard to change the direction of the pacman (left, right, up, down).
Currently, i am using html buttons to redirect the window to the action which changes the variable in a "core" class. It works but not at all times. Pacman moves via javascript timeout function, where each 250 miliseconds, pacman moves in a direction which is stored in mentioned variable. It has sometimes a problem to capture the button click. (i guess because of the js timeout) Any help appriciated!
Mentioned JS code:
<script type="text/javascript">
setTimeout(function () {
window.location.href = '/Home/Move';
}, 250);
</script>
Try this :
document.onkeydown = function(e) {
if (e.keyCode == '38') {
// up arrow
}
else if (e.keyCode == '40') {
// down arrow
}
else if (e.keyCode == '37') {
// left arrow
}
else if (e.keyCode == '39') {
// right arrow
}
}
I was working on Babylon.js when I wanted to make a jump. I found a website and copied it jump code and it works perfectly! But I want to make a real game and I don't want people spamming spacebar to go flying. How could I make it have a few second delay so no one can keep on spamming spacebar and go flying?
function jump(){
camera.cameraDirection.y = 2;
}
document.body.onkeyup = function(e){
if(e.keyCode == 32){
//your code
console.log("jump");
setTimeout(jump(), 1000);
}
}
Link to my game
https://playground.babylonjs.com/#JCE1G3
One option would be to create a persistent boolean variable such as justJumped, and only jump if justJumped is false. When jumping, set justJumped to true, and create a timeout that resets it back to false after the duration of the jump, which looks to be a bit less than half a second:
let justJumped = false;
document.body.onkeyup = function(e) {
if (e.keyCode == 32 && !justJumped) {
justJumped = true;
setTimeout(() => justJumped = false, 400)
console.log("jump");
jump();
}
}
Also note that setTimeout(jump(), 1000); probably isn't doing what you're thinking it does - it invokes jump immediately. If you wanted to call the jump function after 1000ms, just pass the function name itself:
let justJumped = false;
document.body.onkeyup = function(e) {
if (e.keyCode == 32 && !justJumped) {
justJumped = true;
setTimeout(() => justJumped = false, 1400)
console.log("jump");
setTimeout(jump, 1000);
}
}
You can also use other library to achieve it. My favorite one is lodash. You can use _.throttle
var throttled = _.throttle(jump, 1000);
document.body.onkeyup = function(e) {
if (e.keyCode == 32) {
throttled()
}
}
if you don't want to jump immediately after the first key up. you can add option trailing: false
var throttled = _.throttle(jump, 1000, { 'trailing': false });
I've built a custom image viewer that works fine, but each time I use the arrows to view the next or previous image, it loads slower and slower. By the 10th image, it could take many minutes, or even freeze. The snippet I use to open the viewer is the same as the one I use to move to the next image, and each open is always lightning fast; only when I use the arrow keys does it get slower. Sometimes the .php file won't load at all and it'll just say "undefined", which is coming from the JS somewhere, I believe?
function image_load(id) {
$('.view').empty().load(image-viewer.php?id='+id, function() {
$(document).keyup(function(e) {
if (e.keyCode == 39) {
var next = $('#next').attr('alt');
if(next != "null") {
image_load(next);
return false;
}
}
if (e.keyCode == 37) {
var prev = $('#prev').attr('alt');
if(prev != "null") {
image_load(prev);
return false;
}
}
});
});
}
So the next/previous reference the function within which their contained. Is it creating an endless loop somehow and slowing down the processor?
As per my comment, you are creating an endless loop because you are repeatedly binding the key events over and over again. What you should do is separate the function declaration away from event handlers:
var image_load = function(id) {
$('.view').empty().load('image-viewer.php?id='+id);
};
$(document).keyup(function(e) {
// Prevent default key actions
e.preventDefault();
// Evaluate pressed keys
if (e.keyCode == 39) {
var next = $('#next').attr('alt');
if (next) image_load(next);
} else if (e.keyCode == 37) {
var prev = $('#prev').attr('alt');
if (prev) image_load(prev);
}
});
I have a library that creates an editor on the fly (http://epiceditor.com) and also sets up key shortcuts automatically. The shortcuts can be configured in the options so I can't use e.altKey, e.ctrlKey, etc just a heads up.
For some reason the modifier key isn't being set back to false sometimes on Mac/Ubuntu browsers.
On Windows it seems to happen every time. You can reproduce this by clicking render in JSBin then pressing alt+p. You should see "Yay" appear. Now, if on Windows press just p again. You'll see "Yay appear again. Mac and Ubuntu users have seen this same issue occasionally but it's hard to reproduce it.
Also note this only happens with the alt key it seems. Below I have 16 (shift) next to the 18 (alt). If you swap those out it'll work as expected.
The code for the stripped down test case is:
var modKey = false;
var modKeyCode = 18; //16
document.body.addEventListener('keydown', function (e) {
if (!modKey && modKeyCode == e.keyCode) {
modKey = true;
}
if (modKey && e.keyCode == 80) {
console.log('Yay!');
}
});
document.body.addEventListener('keyup', function (e) {
if (modKey && modKeyCode == e.keyCode) {
modKey = false;
}
});
Demo: http://jsbin.com/uhupah/3/edit#javascript,html
I do not have access to my Linux box at the moment, so i cannot test your code.
Thus here is more of a suggestion:
Linux (in my experience) is finicky when it it comes to keyCodes and order of key events. Perhaps combine the if(..) from keyup with that of keydown
if (!modKey && modKeyCode == e.keyCode) {
modKey = true;
} else if (modKey && modKeyCode == e.keyCode) {
modKey = false;
}
The above suggestion is made with assumption that you have no specific requirement to have both 'keydown' and 'keyup'.
I've come up with a fix, albeit a sort of crappy fix, but a fix nonetheless.
The fix I went with was to reset the modifier var when any key combo was successful. I.e. one the p in alt+p is pressed reset the modKey to false like this:
var modKey = false;
var modKeyCode = 18; //16
document.body.addEventListener('keydown', function (e) {
if (!modKey && modKeyCode == e.keyCode) {
modKey = true;
}
if (modKey && e.keyCode == 80) {
console.log('Yay!');
modKey = false; //THIS
}
});
document.body.addEventListener('keyup', function (e) {
if (modKey && modKeyCode == e.keyCode) {
modKey = false;
}
});
The problem with this tho is that you can't do back to back key commands. Most of the time this is alright because the user will do a key command like "save" or "preview" or something, type some more, then do another key command. But you wouldn't be able to, let's say: alt+p s to trigger alt+p then alt+s without having to let go of the alt key.
I am creating a music player which uses the spacebar to pause and play audio, now is it possible to know if someone is currently typing in a textfield, because right now, if this user types in a textfield and audio is playing, when the user presses space the audio pauses, I would like basically that when the user is not in a textfield that a user can just play and pause audio, but when the user is typing that this function is disabled so the audio keeps playing. The code below, is the code I'm am current using for detecting when space is pressed;
//IF Space bar is Pressed
$(window).keypress(function(e) {
if(e.keyCode == 32) {
if(document.getElementById('audio').paused){
if(document.getElementById('video').style.display=="block"){
}
else{
document.getElementById('audio').play();
document.getElementById('pause').style.display="block";
document.getElementById('play').style.display="none";
}
}
else{
if(document.getElementById('video').style.display=="block"){
}
else{
document.getElementById('audio').pause();
document.getElementById('pause').style.display="none";
document.getElementById('play').style.display="block";
}
}
}
});
//END IF Space bar is pressed
Check the event sources tagName attribute:
function(e) {
e = e || event;
var el = e.srcElement || e.target,
cando = !(/textarea|input/i.test(el.tagName));
if(cando && e.keyCode == 32) {
/etc.
}
}
You could also try
if(e.keyCode == 32 && document.activeElement != document.getElementById('someTextBox'))
New code
//IF Space bar is Pressed
$(window).keypress(function(e) {
if(e.keyCode == 32) {
var inputs = document.getElementsByTagName('input');
for(var item in inputs)
{
if(inputs[item] == document.activeElement)
return;
}
if(document.getElementById('audio').paused){
if(document.getElementById('video').style.display=="block"){
}
else{
document.getElementById('audio').play();
document.getElementById('pause').style.display="block";
document.getElementById('play').style.display="none";
}
}
else{
if(document.getElementById('video').style.display=="block"){
}
else{
document.getElementById('audio').pause();
document.getElementById('pause').style.display="none";
document.getElementById('play').style.display="block";
}
}
}
});
//END IF Space bar is pressed
Check if a textarea has focus
if(e.keyCode == 32 && !text_area_has_focus) { ...
Logic for that could be something like this, if you're willing to use jQuery:
if(e.keyCode == 32 && !$('input[type=text]:focus').length) { ...