JavaScript: Preventing Duplicate Keystrokes in Keyboard Input

Currently, I am working on a snake game project as part of my JavaScript course. I have encountered an issue where the game registers a collision when two keys are pressed simultaneously, even though there is no visual collision.

https://i.sstatic.net/j426n.png

This is the code for managing keyboard key inputs:

document.onkeydown = function handleKeyDown(e){
    const key = e.keyCode;
    let newDirection;
    switch(key){
        case 37:
            newDirection = "left";
            break;
        case 38:
            newDirection = "up";
            break;
        case 39:
            newDirection = "right";
            break;
        case 40:
            newDirection = "down";
            break;
        case 32:
            restart();
            return;
        default:
            return;
    }
    snakee.setDirection(newDirection);
}

I am looking for ways to avoid this issue. Someone suggested using the preventDefault() event - should I implement it?

EDIT1

Below is the checkCollision method from the constructor function for the snake object:

this.checkCollision = function(){
            // Code snippet for collision detection
        };

EDIT2:

After considering your feedback, I made some changes to the implementation. Instead of using a switch statement, I switched to an if/else approach.

// Revised keyboard input handling logic
// Code snippet

However, I still face the issue of simultaneous key presses triggering unexpected behavior. When all properties in the map object are false, pressing two keys at once leads to conflicts. I am unsure how to address this problem.

Answer №1

If you are looking for guidance on how to manage simultaneous keystrokes, feel free to check out this example.

To see the custom console.log output, click on the results screen with the console open and press top + left or right keys.

var map = {}; // You may also use an array
onkeydown = onkeyup = function(e){
    e = e || event; // handling IE
    map[e.keyCode] = e.type == 'keydown';
    /* add conditions here */
    console.log(map);
  
  if(map[38] && map[39]) {
    console.log('Moved Top & Right!')
  }
  
    if(map[38] && map[37]) {
    console.log('Moved Top & Left!')
  }
  

}

window.addEventListener('keydown', onkeyup);
window.addEventListener('keyup', onkeydown);

This example was created in response to the query: How to detect if multiple keys are pressed at once using JavaScript?

Answer №2

When we talk about collision, it refers to the interaction between different elements in a system or game. The onkeydown event specifically deals with registering the last key pressed on the keyboard, even if multiple keys are pressed simultaneously.

For example, if you press the keys down and then left, the onkeydown event will only capture the keycode for the left key.

It is unnecessary to use event.preventDefault() as this action would essentially halt the detection of further key presses.

Your current code implementation appears to be functioning correctly based on my observation.

If your intention is to detect multiple keystrokes, one approach is to maintain a map object for that purpose.

const keysPressed = {};
onkeydown = function(e) => {
  const event = e || event;
  keyPressed[event.keyCode] = event.keyCode >= 37 && event.keyCode <= 40;

  // Use the keys pressed to control movement
}

Answer №3

When it comes to game development, one common issue is efficiently managing user actions during gameplay. One effective approach is to use a queuing system, which can involve setting flags or creating an actual queue. Whenever a key is pressed, the user's action is recorded and either flagged for future execution or added to a list.

Your game loop plays a crucial role in monitoring these flags or input queues at the right moment, ensuring that the game state is updated accordingly.

If you're interested in learning how to implement and maintain basic input states in your game, check out this helpful tutorial: https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls

Answer №4

If you switch to using the onkeyup event instead of onkeydown, it should help resolve the collision problem.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transform a complex PHP array into JSON format using JavaScript

I have a three-tiered PHP array with both numeric indices and key-value pairs. I would like to convert it to JSON, and reiterate through the object list. How would I do this? The PHP array is called $main_array, and appears as: Array( [0] => Arra ...

Is my Javascript experiencing a shortage of asyncIds? (Encountered RangeError in inspector_async_hook.js)

One issue that I frequently encounter while using async/await is the following error: RangeError: Value undefined out of range for undefined options property undefined at Set.add (<anonymous>) at AsyncHook.init (internal/inspector_async_hook ...

AJV is failing to validate my body using the function generated by the compile method

Currently, in my API development process with express, I have implemented AJV as a middleware to validate the incoming body data. The version of AJV being used is 6.12.6 Below is the JSON schema named body-foobar.json: { "type": "object& ...

The onChange function does not seem to be functioning properly within the Reactstrap customized input switch

Here is some code: import { CustomInput } from 'reactstrap' ... const changeMediaStatus = (e) => { console.log(e) } ... <CustomInput type="switch" className="ml-auto mr-1" onChange={(e) =>changeMediaStatus ...

Understanding how to use the 'this' variable in Vue components is essential for efficiently modifying DOM elements. Let's dive into a clarification on the usage of 'this'

Within my vue component, the structure is as follows: export default{ name: '', data: function () { return { var1 :{}, var2 : {}, ... } }, created: function () { this.methodName1() }, methods: { me ...

The onchange event is failing to trigger any JavaScript function

I am facing an issue where the onchange event of a dropdown menu is not triggering at all. I even tried redirecting it to a simple JavaScript function for testing purposes, but that didn't work either. I'm struggling to find a solution. Below is ...

How can you execute PHP code within another PHP script without triggering a redirect?

I'm faced with a situation where I have two php files, namely abc.php and def.php. My goal is to only display abc.php in the browser URL bar when it executes. Additionally, upon clicking the submit button on my HTML page, abc.php should be triggered t ...

Create a search feature based on names utilizing Node Express in conjunction with SQL database

After deciding to create an API with a search feature using SQL queries in node express, this is how I structured my code: app.get('/search/:query', (req, res) => { pool.getConnection((err, connection) => { if(err) throw err ...

What is causing setTimeout to not function as intended?

I'm having some trouble moving a <div id="box"> whenever my mouse hovers over it. Currently, the element only moves when I trigger the mouseover event on the div itself instead of when my mouse is actually hovering over it. document.getElements ...

Executing a RESTful API request with Mocha in a Node.js environment

I've been attempting to make a REST call using Mocha. I tried using the "request" framework to log in at auth0. The REST call is correct; I tested the same data in Postman and received the correct response. However, when trying to implement the call ...

What is the method to identify the key responsible for triggering a textbox input event?

Suppose there is a textbox on the webpage: <input id='Sub' type='text'> To capture each time the input changes, you can use the following code: sub = document.getElementById('Sub'); sub.addEventListener('input&a ...

The color input click event does not work properly when triggered within a context menu event

This may sound a bit complicated, but let me try to explain it clearly. I'm working on a web app where I want users to be able to change the background color of certain divs. I plan to use a color picker interface for this purpose and utilize the con ...

Has anybody managed to successfully implement this require or debug NPM module for use in a web browser?

Has anyone successfully implemented the require or debug NPM modules in a browser environment? Despite claims and instructions on the debug NPM module's page that it can be used in the browser, attempting to do so results in the following error: Unc ...

Guide on incorporating pinching gestures for zooming in and out using JavaScript

I have been working on implementing pinch zoom in and out functionality in JavaScript. I have made progress by figuring out how to detect these gestures using touch events. var dist1=0; function start(ev) { if (ev.targetTouches.length == 2) {//checkin ...

Steps to implement a print modal with JavaScript, jQuery and more

Imagine having a print button on several pages that, when clicked by the user, triggers a modal to pop up with the content for printing. Any suggestions or ideas would be greatly appreciated. I have multiple pages with a print button. When the user clicks ...

Implementing JavaScript logic to proceed to the following array within a 3D array once a specific condition is met

I'm currently tackling a challenge that requires me to obtain a specific number using a given 3D array. This array consists of 2D arrays, each containing the same number repeated x times. The parent array is sorted from largest to smallest. Here&apos ...

Navigating a dynamic table by looping through its generated tr elements

I am currently working with a dynamically created tr table that includes individual rows of data and a fixed total sum at the bottom. The total sum does not change dynamically. var tmp = '<tr id="mytable"> <td id="warenid">'+data1.id ...

Place an image in the middle of a div with text aligned to the right side

How do I center an image within a div that has text on the right side? The page layout is based on percentages and I want the image to be perfectly centered with the text floated to the right. This is what I currently have: IMG.logo { display: block ...

What could be causing setTimeout to trigger ahead of schedule?

I am struggling with a piece of node.js code like this: var start = Date.now(); setTimeout(function() { console.log(Date.now() - start); for (var i = 0; i < 100000; i++) { } }, 1000); setTimeout(function() { console.log(Date.now() - s ...

Issues with displaying graphs using Angular.js, Highcharts, and Phantomjs PDF printer has been encountered

I am facing a peculiar issue with my Angular.js application that uses Highcharts for graph rendering. The application needs to support PDF printing, which is achieved through our company's Phantomjs PDF service. Graphs are generated using a custom di ...