Reputation: 26
I'm trying to implements movement in a 3D game, for this to work I have to deal with multikeys detection.
So I got this to work
setControls(){
this.keyMap = {};
window.addEventListener('keydown', this.onMove.bind(this));
window.addEventListener('keyup', this.onMove.bind(this));
}
onMove(event){
this.keyMap[event.key] = event.type === "keydown";
//Move according to key pressed
}
The keydown event works fine, my object moves on two directions at the same time when 2 keys are pressed. But when the keyup event is fired, keyMap is set to proper values but onMove is called just once, and even though there's still one key pressed my keyMap is not updating anymore.
I tried a few things that got me into an infinite loop.
Thanks.
Upvotes: 0
Views: 495
Reputation: 36331
When creating a game with input, don't put the logic of the movement within the key press itself. Instead have a "Main Game Loop" that will move the object based on whether or not an input value is set in your keymap.
Placing the movement logic within the input causes the input to get delayed so there will be a pause between the initial input and the following inputs making the movement look and act strangely. By adding it to your game logic instead of the input event you will not see that delay.
Here is an example it doesn't use a canvas or anything, but it demonstrates the point (use WASD
to move):
const player = document.querySelector('.player')
const playerSpeed = 2
let x = 0, y = 0
const keyMap = {
a: false, d: false,
w: false, s: false
}
window.addEventListener('keydown', setKey)
window.addEventListener('keyup', setKey)
function setKey(event) {
keyMap[event.key] = event.type === 'keydown'
}
// Main Game loop
setInterval(() => {
// Calculate the internal x position
if (keyMap.a) { x -= playerSpeed }
if (keyMap.d) { x += playerSpeed }
// Calculate the internal y position
if (keyMap.w) { y -= playerSpeed }
if (keyMap.s) { y += playerSpeed }
// Set the new position of the player
// based on the internal x/y position
player.style.left = x + 'px'
player.style.top = y + 'px'
}, 10)
.player {
background: red;
position: absolute;
height: 50px;
width: 50px;
}
<div class="player"></div>
Upvotes: 2