Detect the initial collision exclusively (Collision detection using raycasting)

I am currently working on a never-ending runner game where a character is positioned at (0,0) and can only move along the X-axis by using arrow keys or the mouse. There are two different types of objects moving from z = -10000 towards the character, and once they reach z = 10000 (i.e., behind the character and offscreen), they are reset back to z = -10000. To detect collisions between the character and these objects, I am utilizing raycasting code.

The raycasting involves shooting rays from each vertex of the character every frame within the render loop. If these rays intersect with one of the object's vertices at a distance close to the character (the exact distance isn't clear), then a collision is registered.

This is the snippet of my code:

Code running inside the render loop:

detectCollisionRaycaster(character, objectsArray);

Function for collision detection:

let cooldown = false;
let objectMesh;
let collisionResults;

function detectCollisionRaycaster(originObject, collidedObjects) {

let originPoint = originObject.position.clone();

    for (var vertexIndex = 0; vertexIndex < objectMesh.geometry.vertices.length; vertexIndex++) {
        var localVertex = objectMesh.geometry.vertices[vertexIndex].clone();
        var globalVertex = localVertex.applyMatrix4( objectMesh.matrix );
        var directionVector = globalVertex.sub( objectMesh.position );

        var raycaster = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
        collisionResults = raycaster.intersectObjects( collidedObjects, true );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() && !cooldown) {

            cooldown = true;

            console.info("Object Collided");

            setTimeout(function(){
                collisionResults.length = 0;
                cooldown = false;
            }, 500);

        }
    }
}

The Issue

The collision code triggers multiple times, most likely because the objects are approaching the character causing their vertices to collide with the rays over several frames. This results in the collision code being executed repeatedly as long as the object remains "inside" the character.

Desired Outcome:

I aim for the collision detection code to activate only once, pause collision assessment for a specific duration until there is no more collision with the character, and then resume collision detection.

Attempted Solutions

Initially, I tried implementing a timeout function within the collision-detection code to halt the continuous execution until the specified time elapsed. However, this approach merely caused the code to run once, delay for the timeout duration, and then resume executing the collision detection code for all instances the object was inside the character's space.

Answer №1

When a collision is found, the loop does not terminate and continues executing all iterations even when the if condition is satisfied.

To improve your logic organization, consider splitting the responsibility of your previous collision detection method into two separate methods. One method, isCollision, simply checks for a collision, while the other method utilizes isCollision to properly set the appropriate cooldown upon collision detection.

let cooldown = false;
let objectMesh;
let collisionResults;
let timeout;

function detectCollisionRaycaster(originObject, collidedObjects) {
    if (this.isCollision(originObject, collidedObject)) {
        cooldown = true;
        if (timeout) {
           clearTimeout(timeout);
        }
        timeout = setTimeout(function () {
            cooldown = false;
        }, 500);
    }
}

function isCollision(originObject, collidedObjects) {
    let originPoint = originObject.position.clone();

    for (var vertexIndex = 0; vertexIndex < objectMesh.geometry.vertices.length; vertexIndex++) {
        var localVertex = objectMesh.geometry.vertices[vertexIndex].clone();
        var globalVertex = localVertex.applyMatrix4( objectMesh.matrix );
        var directionVector = globalVertex.sub( objectMesh.position );

        var raycaster = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
        collisionResults = raycaster.intersectObjects( collidedObjects, true );
        if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() && !cooldown) {
            console.info("Object Collided");
            return true;
        }
    }

    return false;
}

Edit: The cooldown will persist until there are no collisions with the player. If you wish to pause specifically for the object triggering the collision, keep a reference to that object and check against it instead of checking against all player vertices + objects. You can modify the isCollision method to return the colliding object instead of a boolean, then create another method to cast rays from that object to the player vertices to determine when the collision ends.

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

A comprehensive guide on associating a JavaScript function with an element attribute

I am looking for a way to assign a JavaScript function to an HTML attribute. For example: <li data-ng-repeat="job in jobList" class= dynamicClass(str) data-filter = "dynamicFilter(str)"> The reason I want to do this is because the class name and ...

The Faux-Dynamic News Feed on a stationary website

As I work on revamping my employer's static website, it has become clear that a news section needs to be integrated. The site is being built using the Bootstrap 3.0 framework. My plan is to implement the following strategy: I aim to have a JavaScrip ...

Is there a way to verify the existence of an element based on its class name?

In the title of my question, I mentioned that my element lacks an id attribute. So how can I determine if it exists or not? Here is the HTML code: <div class="classname">something</div> Note1: If there was an id attribute like this: var el ...

Steps to indicate a cucumber test as incomplete using a callback function in a node environment

Can a cucumber test in Node be flagged as pending to prevent automated test failures while still specifying upcoming features? module.exports = function() { this.Given(/^Scenario for an upcoming feature$/, function(callback) { callback(); } ...

Guide on executing YUI tests in headless mode and recording outcomes in a log document

I currently have some YUI tests that I need to run in headless mode. Right now, these tests are executed by launching their corresponding TestFileName.html. As a result, the browser displays the test results with green and red icons along with messages ind ...

Vue event manager, accessible for all components

I have created a new Vue instance and assigned it to the window object, thinking that it would be accessible throughout all components. I expected this setup to allow me access to events emitted anywhere within my application. However, it seems like this ...

Tips for reducing the size of the sidebar when navigating to a specific page

I have a sidebar that I want to minimize when the user enters the index page. There is a button in the sidebar for that: <a class="mobile-menu" id="mobile-collapse" href="javascript:"><span></a> How can I au ...

Ajax Multidimensional Array Response

Currently, I am attempting to retrieve a Multiarray response from an ajax Post JSON request. After numerous attempts, I am hopeful that I can get assistance here... JS AJAX RESPONSE var data = { "myid": "1234" }; $(".the-return").html(""); $.ajax({ ...

Are there problems with the response values of functions that can handle varying object interfaces?

Currently in the process of developing a command line blackjack app with Node and Typescript, even though I am relatively new to Typescript. My main challenge lies in implementing interfaces for player and dealer objects, as well as creating functions that ...

Displaying images retrieved from firebase on a React.js application

Currently, I am attempting to retrieve images from Firebase storage and then exhibit them in a React component. As a newcomer to React/Javascript, I find it challenging to grasp the asynchronous nature of React/JS. The issue I'm facing is that althoug ...

Having trouble saving the table in .json format to the directory

I've been attempting to extract data from a website using web scraping, but I'm struggling to figure out how to convert the data into a .json format and display it in the console. const puppeteer = require('puppeteer-extra'), // in pyth ...

How to pass event data when clicking on a div using React

I'm curious about how the onClick event flows in React when clicking on a div. In my application, there's a ParentComponent that renders a ChildComponent which generates a div for each item in the props.options array. I have a couple of questio ...

Utilizing Vue.js to dynamically add a class through computed properties

As a beginner in Vue.js, I want to dynamically add or remove classes based on certain conditions. Specifically, I am trying to remove the success class when the total sum exceeds 25, but for some reason the color is not changing as expected. Can anyone p ...

I encountered an issue with passing arguments in the invoke function I redesigned

I am currently attempting to replicate the functionality of the .invoke() function. Although I can successfully call the function, I am facing difficulties when it comes to passing arguments. I have made attempts using call and apply, but unfortunately, I ...

Learn the step-by-step process of dynamically adding elements to a JavaScript object in JSON structure

We are attempting to dynamically generate a JSON object using a for loop. The intended result should resemble the following: posJSON = [ { "position": [msg[0].Longitude, msg[0].Latitude], "radius": 0.05, "color": [255, 255, 0, ...

Ways to guarantee that a link is deactivated upon page load

I'm facing two issues Here is the markup for the link: <a href="/Home/DisplaySpreadSheetData" id="displaySpreadSheetLink">DisplaySpreadsheetData</a> 1) I'm trying to disable the link by default under document.ready ...

Loop through the JSONP object to display its properties

When I receive this object through jsonp, it has the following structure: "item1": { "child1": { "nr": 123, "money": "USD", "Date": "12.12.2016, 17:00", "asw1": 13, "SpecialField" ...

Managing the `selected` property of an option in React/NextJS

I have been working on a website and encountered an issue with a dynamic select box in React. Despite the functionality of my app being intact, I am struggling to add the selected property to an option once it is chosen. Is there a more effective way to ...

Explore the Filter List without being affected by the arrangement of words or the level of search precision

I was able to resolve the issue by adjusting my search filter algorithm. Now, I can search regardless of word order, but the results are not as specific as I need them to be. When I type "Correy" in the search bar, it shows all results containing that wo ...

Why won't both routes for Sequelize model querying work simultaneously?

Currently, I am experimenting with different routes in Express while utilizing Sequelize to create my models. I have established two models that function independently of one another. However, I am aiming to have them both operational simultaneously. A sea ...