Leveraging .intersect/.intersectsBox to handle object collisions in threeJS

Currently, I am developing a simple breakout/arkanoid game using threeJS. The game features a paddle and a bouncing ball on the screen. My main focus right now is to make the collision detection work correctly so that when the ball hits the paddle, it bounces away. I have been attempting to use bounding boxes for this purpose, but I am facing an issue where the .intersect/.intersectsBox methods are not detecting the collision as expected. Below is the code snippet that I have been working on -

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const geometry = new THREE.BoxGeometry(5, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
var cubeBoxHelper = new THREE.BoxHelper(cube, 0xff0000);
var boundingBoxPaddle = new THREE.Box3().setFromObject(cubeBoxHelper);
cubeBoxHelper.update();

const geometrySphere = new THREE.SphereGeometry(1, 32, 32);
const materialSphere = new THREE.MeshBasicMaterial({ color: 0xffff00 });
const sphere = new THREE.Mesh(geometrySphere, materialSphere);
var sphereBoxHelper = new THREE.BoxHelper(sphere, 0xff0000);
var boundingBoxBall = new THREE.Box3().setFromObject(sphereBoxHelper);
sphereBoxHelper.update();

scene.add(cube, cubeBoxHelper, sphere, sphereBoxHelper);

sphere.position.y = 5;
camera.position.z = 15;
camera.position.y = 10;

var xSpeed = 0.0005;
var dx = 0.1;
var dy = 0.1;

function bounce()
{
    if (sphere.position.x < -19 || sphere.position.x > 18.5)
    {
        dx = -dx;
    }
    if (sphere.position.y < -5 || sphere.position.y > 19)
    {
        dy = -dy;
    }
    sphere.position.x += dx;
    sphere.position.y += dy;
    sphereBoxHelper.update();
}

function intersect()
{
    if (boundingBoxBall.intersect(boundingBoxPaddle) == true)
    {
        console.log("Intersection Detected");
    }
}

const animate = function ()
{
    requestAnimationFrame(animate);

    document.addEventListener("keydown", onDocumentKeyDown, false);
    function onDocumentKeyDown(event)
    {
        var keyCode = event.which;
        if (keyCode == 65 && cube.position.x >= -18.5)
        {
            cube.position.x -= xSpeed;
        }
        else if (keyCode == 68 && cube.position.x <= 18)
        {
            cube.position.x += xSpeed;
        }
        cubeBoxHelper.update();
    };
    bounce();
    intersect();
    sphereBoxHelper.update();
    renderer.render(scene, camera);
};

animate();

Currently, the intersect function simply logs to the console for debugging purposes. Any assistance on resolving this issue would be greatly appreciated as I am unsure of where the problem lies.

Answer №1

Box3.intersect

.intersect ( box : Box3 ) : this box - Box to intersect with.

When you use this function, it calculates the intersection of the current box and another box specified, adjusting the dimensions of this box accordingly. If there's no overlap between the two boxes, it makes this box empty.

The main purpose of this function is to update boundingBoxBall based on boundingBoxPaddle, and it may even result in boundingBoxBall being set as an empty box!

Based on your requirements, the function you probably need is:

Box3.intersectsBox

.intersectsBox ( box : Box3 ) : Boolean box - Box to check for intersection against.

This function determines whether there's any intersection between this box and the specified box.

With the intersectsBox function, you'll get a straightforward true/false response to indicate if the two boxes have collided.

Remember, the bounding box is dependent on the associated geometry. So, if you transform the Mesh, you'll also need to transform the bounding box accordingly. This crucial point is highlighted in the example code provided on the Box3 docs:

const box = new THREE.Box3();

// ...

// To get the current bounding box with the world matrix during animation loop
box.copy( mesh.geometry.boundingBox ).applyMatrix4( mesh.matrixWorld );

Complete Example:

let W = window.innerWidth;
let H = window.innerHeight;

// Initialize renderer
const renderer = new THREE.WebGLRenderer({
  antialias: true,
  alpha: true
});
document.body.appendChild(renderer.domElement);

// Create scene
const scene = new THREE.Scene();

// Set up camera
const camera = new THREE.PerspectiveCamera(28, 1, 1, 1000);
camera.position.set(0, 0, 50);
camera.lookAt(scene.position);
scene.add(camera);

// Add lighting
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, -1);
camera.add(light);

// Define geometries and materials for objects
let geo = new THREE.BoxBufferGeometry(5, 5, 5);
geo.computeBoundingBox();
let mat = new THREE.MeshPhongMaterial({
  color: "red"
});
const left = new THREE.Mesh(geo, mat);
left.position.set(-15, 0, 0)
scene.add(left);
const right = new THREE.Mesh(geo, mat);
right.position.set(15, 0, 0)
scene.add(right);

geo = new THREE.SphereBufferGeometry(1, 16, 16);
geo.computeBoundingBox();
mat = new THREE.MeshPhongMaterial({
  color: "yellow"
});
const ball = new THREE.Mesh(geo, mat);
scene.add(ball);

// Function to render scene
function render() {
  renderer.render(scene, camera);
}

// Function to resize window
function resize() {
  W = window.innerWidth;
  H = window.innerHeight;
  renderer.setSize(W, H);
  camera.aspect = W / H;
  camera.updateProjectionMatrix();
  render();
}

// Initialize animation variables
let rate = 0.1;
let goingRight = true;
let ballBox = new THREE.Box3();
let wallBox = new THREE.Box3();

// Animation loop
function animate() {
  render();

  ball.position.x += ((goingRight) ? 1 : -1) * rate;
  ball.updateMatrix();
  ball.updateMatrixWorld(true);

  ballBox.copy(ball.geometry.boundingBox);
  ballBox.applyMatrix4(ball.matrixWorld);

  if (goingRight) {
    wallBox.copy(right.geometry.boundingBox);
    wallBox.applyMatrix4(right.matrixWorld);
    if (ballBox.intersectsBox(wallBox)) {
      goingRight = false;
    }
  } else {
    wallBox.copy(left.geometry.boundingBox);
    wallBox.applyMatrix4(left.matrixWorld);
    if (ballBox.intersectsBox(wallBox)) {
      goingRight = true;
    }
  }

  requestAnimationFrame(animate);
}

// Event listener for window resize
window.addEventListener("resize", resize);

// Initial resize
resize();

// Start animation
requestAnimationFrame(animate);
html,
body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  overflow: hidden;
  background: skyblue;
}
<script src="https://threejs.org/build/three.min.js"></script>

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

Steps to invoke another service (function) prior to calling the res.view() function in sails JS:

I am looking to execute a separate function, like a Service function, before Sails renders the page into HTML. Please refer to the controller code below... var MYController = { index: function(req, res, next) { req.flash("error", "Testing hello ...

Ways to access a JavaScript function on a div with multiple identifiers

Currently working on developing a discussion panel using ASP.net, where each comment is assigned a unique id. I am looking to trigger the jQuery click function whenever a user clicks on a comment. However, since the comment ids are dynamically assigned an ...

What is the way to instruct Mongoose to exclude a field from being saved?

Is there a way in Mongoose to instruct it to not save the age field if it's null or undefined? Or is there a method to achieve this in Express? Express router.put('/edit/:id', function(req, res) { Person.findOneAndUpdate({ _id: req.p ...

AngularJS: Compile a particular template

One pre tag on the page contains dynamic text that is unknown during page load. This text may include ng commands, as shown below: <pre> Hello <span ng-click="test('args')">world</span> angular-JS! </pre> Since these ...

Utilizing the power of dynamic variable naming within ng-repeat

Has anyone ever tried using a similar approach? I am having trouble parsing {{}} within an ng-repeat. It works fine with ng-options. <option value="" ng-repeat="k in selected_grp_keys_{{value.key.id}}" value="{{k.id}}" ng-selected="k.id == value.fk_k ...

Struggling to constrain a TextField component from material-ui and encountering an issue with the inputRef

Currently, I am attempting to restrict the length of an autocomplete textfield within my project. However, when I apply InputProps={{ maxLength: 2 }}, it throws an error stating that my inputRef.current is null. Even though I have set the ref in the inputR ...

How to automatically close the menu on a Wordpress theme after clicking a link

I am currently using a Wordpress theme named ichiban, which can be viewed by following this link. Within this theme, I have created custom menu items that are designed to link directly to different sections on the same page. However, I am encountering an i ...

Issue with Datatables FixedColumns plugin in IE8/7 and Firefox

I am encountering issues with the FixedColumn plugin on IE8, IE7, and Firefox. All of them are causing my table to malfunction, displaying the following error: Error: Invalid argument. Line: 566 Char: 3 Code: 0 URI: ./resources/javascript/dataTable/Fixed ...

Updating the titles of Bootstrap 4 Switches on the fly

Currently utilizing Bootstrap 4 Toggle on my website, I'm struggling to figure out how to dynamically modify the labels on the toggles at runtime. My objective is to implement a toggle-switch that, once activated, displays a countdown indicating the ...

Applying CSS to an iframe using JavaScript: A Step-by-Step

I have an Iframe editor and I am trying to change some CSS inside the editor. However, when I attempt to apply the CSS, it does not affect the styles within the Iframe. <div id="editor" style="flex: 1 1 0%;"> <iframe src="https://editor.unlay ...

Create a circle-shaped floor in THREE.JS that mimics the appearance of a shadow

I am working on creating a circle mesh with a gradient material that resembles a shadow effect. Specifically, I want the circle to have a black center and fade to almost white at the edges. Currently, I have been able to create a circle and position it co ...

Tips for consuming a REST API to retrieve JSON data and assign it to a variable for use in React JS

I'm currently working on developing a shopping application using React.js. I found inspiration from a sample application on https://codepen.io/paulkim/pen/oZLavq , and now I am looking to fetch product information from an API call. I have attempted to ...

Acquiring the input from a text box to generate a hyperlink on the current page

I am trying to generate a link that has the href attribute as follows: app\process?val=12000 The catch is that the value for the val parameter (in this case 12000) needs to be derived from a textbox on the page. I am aware that I can retrieve the ...

Creating a path with a specific width similar to the lineTo method in canvas 2d

Is there a way to create a path with a specific width using Three.js, similar to canvas 2d lineTo? I have tried using THREE.Line but encountered limitations where the width couldn't exceed 1 on certain platforms. Are there any alternatives available t ...

The .SVC file's generated Javascript proxy URL fails to function properly when used with SSL

The ASP.Net web site I have deployed in IIS 7.5 includes a file named Cart.svc, which is used for accessing JavaScript from the browser. While the JavaScript functions fine without SSL, enabling SSL causes it to stop working. Interestingly, removing the / ...

Assistance requested in structuring JSON data

I'm currently working on making my javascript code more dynamic. Here's what I have so far: data.addRows(2); data.setValue(0, 0, 'name goes here'); data.setValue(0, 1, value 1 goes here); data.setValue(0, 2, value 2 goes here); data. ...

Complete the modal window form

I'm currently facing an issue with populating a modal window form. To provide some context, when I click on a grid row to edit a user, I make an ajax call which fetches specific data related to that user. Here is the existing code snippet: <modal ...

The ID value did not pick up the number 0 when passed to the next blade after the initial reading

When passing an ID value to another blade file, I encountered an issue where the other blade file did not read the number 0 at the beginning. For example, if I pass the value of 006, when I console log the value in the other blade view, it only shows 6. H ...

Having trouble downloading a PDF file on a local server with React and the anchor tag element

Having trouble downloading a pdf file from my react app to my Desktop. I've reached out for help with the details How to download pdf file with React. Received an answer, but still struggling to implement it. If anyone new could provide insight, that ...

When selecting a different file after initially choosing one, the Javascript file upload event will return e.target as null

Currently, I have implemented file uploading using <input>. However, when attempting to change the file after already selecting one, the website crashes and states that event.target is null. <Button label="Upload S3 File"> <input ...