I am having a problem when I move my key controls mainly the arrows on the keyboard. If the viewpoint is small enough it also moves the screen up and down because of the vertical side bar and the tetris piece at the same time. And I want the pieces to only move when I press the arrows. I am a novice at Js and I am not sure where to start to solve the problem, suggestions to where to start to look at?
Here is my Js script
document.addEventListener("keydown", CONTROL);
function CONTROL(event) {
if (event.keyCode == 37) {
p.moveLeft();
dropStart = Date.now();
}
else if (event.keyCode == 38) {
p.rotate();
}
else if (event.keyCode == 39) {
p.moveRight();
dropStart = Date.now();
}
else if (event.keyCode == 40) {
p.moveDown(0);
}
}
Arrow keys moving the browser window is a default browser behavior.
Use event.preventDefault()
To listen only to arrow keys use if (k >= 37 && k <= 40) {, or the opposite: if (k < 37 || k > 40) return;
const p = { // JUST FOR THIS DEMO. You use Piece.prototype
moveLeft() { console.log("LEFT"); },
rotate() { console.log("ROTATE"); },
moveRight() { console.log("RIGHT"); },
moveDown() { console.log("DOWN"); },
};
document.addEventListener("keydown", CONTROL);
function CONTROL(event) {
const k = event.keyCode;
if (k < 37 || k > 40) return; // Do nothing if was not an arrow key. Else Do:
event.preventDefault(); // Prevent browser scroll on arrows
if(k == 37 || k == 39) dropStart = Date.now(); // Only for left or right
return {
37: p.moveLeft,
38: p.rotate,
39: p.moveRight,
40: p.moveDown
}[k]();
}
html, body {min-height: 100%;}
so the problem here is that is that it's sensing each key individually (I've had the same problem so you need a keymap to keep track off ALL the keys pressed like so:
var keys = [];
function keysPressed(e) {
keys[e.keyCode] = true;
}
function keysReleased(e) {
keys[e.keyCode] = false;
}
if(keys[37] === true){
//do stuff here
}
if(keys[38] === true){
//do stuff here
}
You may also want to use the proper identifier "==="
Related
The code works in the following way:
- holding shoot/drop button generate bullet and the bomb that is drawn/shown in canvas,
- it executes all the time in the function draw that refreshes around 60times per second.
Instead I want to set sth as:
- setInterval(shoot, 1000);
- setInterval(drop, 2000);
so it should be like:
- when user presses the key, it creates the bullet/bomb with the interval of 1/2 seconds
- it should all happen without realising the key
Below I provide the sample code:
let left = false;
let up = false;
let right = false;
let down = false;
let shoot = false;
let drop = false;
document.onkeydown = function (e) {
if (e.keyCode == 37) left = true;
if (e.keyCode == 38) up = true;
if (e.keyCode == 39) right = true;
if (e.keyCode == 40) down = true;
if (e.keyCode == 17) shoot = true;
if (e.keyCode == 32) drop = true;
e.preventDefault();
}
document.onkeyup = function (e) {
if (e.keyCode == 37) left = false;
if (e.keyCode == 38) up = false;
if (e.keyCode == 39) right = false;
if (e.keyCode == 40) down = false;
if (e.keyCode == 17) shoot = false;
if (e.keyCode == 32) drop = false;
e.preventDefault();
}
function draw() {
requestAnimationFrame(draw);
if (shoot) {
bullet = new Bullet(player.x - 3, player.y - 3, 6, 10)
bullets.push(bullet);
}
for (i = 0; i < bullets.length; i++) {
bullets[i].show();
bullets[i].move();
}
if (drop) {
bomb = new Bomb(player.x - 8, player.y + 50, 16, 1)
bombs.push(bomb);
}
for (i = 0; i < bombs.length; i++) {
bombs[i].show();
bombs[i].move();
}
}
requestAnimationFrame(draw);
Full code on remote server:
https://stacho163.000webhostapp.com
Is that a way to do it in my code or i have to change the way the buttons work?
If there is a solution without jQuery, that would be great.
e: checked the first tip, but after creating the first single bullet/bomb it's working as it was before.
Thank you for your tips :)
You should set some sort of wait variable, that indicates that the key is currently pressed, and no processing needs to take place:
let dropping = false;
// indicates that the bomb is dropping right now. Do not drop a new bomb
//...
if (e.keyCode == 32) {
drop = true;
dropping = true;
setTimeout(function () { dropping = false; }, 1000);
// if 1 second has passed, reset the dropping variable, to allow another bomb to drop
}
//...
if (drop && !dropping) {
bomb = new Bomb(player.x - 8, player.y + 50, 16, 1)
bombs.push(bomb);
}
This way, your bomb will only drop once every 1 second. Rinse and repeat :)
I tried with this code to detect two keyboard arrows being simultaneously pressed:
document.addEventListener('keydown', event => {
if (event.keyCode === 38) {
console.log('up Arrow')
}
if (event.keyCode === 39) {
console.log('right Arrow')
}
})
But it doesn't work, however hard I try to press them at exactly the same time.
How can I cleanly fix this and detect when both keys are down ?
There's only one keyCode per event. You have to track the keys going down, and up:
// if you keep both up and down keys down, you'll get a message
let downKeys = {}; // the set of keys currently down
document.addEventListener('keydown', event => {
downKeys[event.keyCode] = true;
if (downKeys[38] && downKeys[40]) {
console.log("both down!");
}
});
document.addEventListener('keyup', event => {
downKeys[event.keyCode] = false;
});
(you have to go full page to test this snippet)
Here I use 2 flags to check if you are holding the keys.
If both flags are true then it means that you are holding both keys. So, you can perform anything inside the condition.
let holdKeyUp = false;
let holdKeyRight = false;
document.addEventListener('keydown', event => {
if (event.keyCode === 38) {
holdKeyUp = true;
}
if (event.keyCode === 39) {
holdKeyRight = true;
}
if (holdKeyUp && holdKeyRight) {
console.log("Both keys are pressed.");
}
})
document.addEventListener('keyup', event => {
if (event.keyCode === 38) {
holdKeyUp = false;
}
if (event.keyCode === 39) {
holdKeyRight = false;
}
})
I have a dashboard page that has a left pane which slides on click. I want to make the same thing happen on pressing the Left Arrow and the Right Arrow keys.
Can anybody help me on this? I could do it on click. Below is my solution:
$(document).ready(function() {
$('#opener, .left-panel-head').on('click', function() {
var panel = $('#LeftPanel');
if (panel.hasClass("visible")) {
panel.removeClass('visible').animate({'margin-left': '-300px'});
$('#rightPanel').animate({'width': '100%'});
} else {
panel.addClass('visible').animate({'margin-left': '0px'});
$('#rightPanel').animate({'width': '74%'});
}
return false;
});
});
function updatePanel(direction) {
if(direction === 'left') {
// pressing left
}else if(direction === 'right') {
// pressing right
}
};
$(document).keypress(function( event ) {
if(event.which == 37) {
updatePanel('left');
}else if(event.which == 39) {
updatePanel('right');
}
};
$('#opener, .left-panel-head').on('click', updatePanel('left'));
$('#opener, .right-panel-head').on('click', updatePanel('right'));
You can make your function an actual function instead of an anon function passed into your click event and then call it from multiple places.
(function($, document){
var $document = $(document);
//shared function
function stuff(){
}
//check if key pressed was one of the left or right arrows
function checkKey(e){
var c = e.which ? e.which : e.keyCode;
//left arrow, right arrow
if(c === 37 || c === 39){
//call stuff if left or right arrow was pressed
stuff();
}
}
//call stuff on click
$('#opener, .left-panel-head').on('click', stuff);
$document.on('keydown', checkKey);
})(jQuery, document);
I'm looking for a KeyListener for a game I'm developing in JavaScript. I have no idea how this would work in real code but it would be something like this:
if(keyPress == upKey)
{
playerSpriteX += 10;
}
else if(keyPress == downKey)
{
playerSpriteY -= 10;
}
etc...
I searched it up, and Google came up with things that involved AJAX which I don't understand yet. Is there a built in function in JavaScript that does this?
Here's an update for modern browsers in 2019
let playerSpriteX = 0;
document.addEventListener('keyup', (e) => {
if (e.code === "ArrowUp") playerSpriteX += 10
else if (e.code === "ArrowDown") playerSpriteX -= 10
document.getElementById('test').innerHTML = 'playerSpriteX = ' + playerSpriteX;
});
Click on this window to focus it, and hit keys up and down
<br><br><br>
<div id="test">playerSpriteX = 0</div>
Original answer from 2013
window.onkeyup = function(e) {
var key = e.keyCode ? e.keyCode : e.which;
if (key == 38) {
playerSpriteX += 10;
}else if (key == 40) {
playerSpriteX -= 10;
}
}
FIDDLE
The code is
document.addEventListener('keydown', function(event){
alert(event.keyCode);
} );
This return the ascii code of the key. If you need the key representation, use event.key (This will return 'a', 'o', 'Alt'...)
JSFIDDLE DEMO
If you don't want the event to be continuous (if you want the user to have to release the key each time), change onkeydown to onkeyup
window.onkeydown = function (e) {
var code = e.keyCode ? e.keyCode : e.which;
if (code === 38) { //up key
alert('up');
} else if (code === 40) { //down key
alert('down');
}
};
Did you check the small Mousetrap library?
Mousetrap is a simple library for handling keyboard shortcuts in JavaScript.
A bit more readable comparing is done by casting event.key to upper case (I used onkeyup - needed the event to fire once upon each key tap):
window.onkeyup = function(event) {
let key = event.key.toUpperCase();
if ( key == 'W' ) {
// 'W' key is pressed
} else if ( key == 'D' ) {
// 'D' key is pressed
}
}
Each key has it's own code, get it out by outputting value of "key" variable (eg for arrow up key it will be 'ARROWUP' - (casted to uppercase))
I feel like a complete klutz, I had this working and then I accidentally forgot to save it! I'm an idiot. I've spent the last day trying to recreate what I had but I can't do it. Basically (from my last save) I had this:
function canvasMove(e) {
if(!e) var e = window.event;
var downcheck;
var upcheck;
var leftcheck;
var rightcheck;
if(e.keyCode == '38') {
if(up + down == 0) downcheck = false;
else downcheck = true;
e.preventDefault();
}
if(e.keyCode == '40') {
if(up + down > HEIGHT - 110) upcheck = false;
else upcheck = true;
e.preventDefault();
}
if(e.keyCode == '37') {
if(left + right == 0) rightcheck = false;
else rightcheck = true;
e.preventDefault();
}
if(e.keyCode == "39") {
if(left + right > WIDTH - 110) leftcheck = false;
else leftcheck = true;
e.preventDefault();
}
if(leftcheck == true) { left += 10; counting() };
if(rightcheck == true) { right -= 10; counting() };
if(upcheck == true) { up += 10; counting(true) };
if(downcheck == true) { down -= 10; counting(true) };
}
The problem of course being that Javascrpt doesn't support the ability to check if two keys are being pressed at the same time. What I want to accomplish is when the user pressed up and left they'll move diagonally. Ignore the "counting" function, it's just to keep track of how much the user has moved.
I managed to accomplish this with just else and if statements, no less! So I was wondering if you guys could give it a shot. The first if statement in each key if statement is so the user can't leave the canvas box. Then I have a function that moves the user by redrawing the canvas.
function redraw() {
clear(draw);
draw.fillStyle = 'rgba(0,0,0,0.5)';
draw.fillRect(left + right, up + down, '100', '100');
}
The "clear" function is just a simple function that clears the entire canvas. This is all controlled by an init function that looks like this:
function init() {
canvas = document.getElementById('game');
HEIGHT = canvas.height;
WIDTH = canvas.width;
draw = canvas.getContext('2d');
setInterval(redraw, 30);
document.onkeydown = canvasMove;
}
Your -check flags need to be global variables rather than function-scoped variables, otherwise they will never stay set between keydown events (handling only one key at a time). You also need a keyup event handler that will unset the correct flag when a key is released.