【问题标题】:Using .intersect/.intersectsBox for object collision threeJS使用 .intersect/.intersectsBox 进行对象碰撞threeJS
【发布时间】:2021-05-07 23:17:34
【问题描述】:

您好,我正在用 threeJS 开发一个基本的突围/打砖块游戏。现在我只有一个桨和一个在屏幕上弹跳的球。我试图让碰撞工作,以便当球击中桨时,它会弹开。我一直在尝试使用边界框来实现这一点,但是我遇到了一个问题,即 .intersect/.intersectsBox 没有正确注册交叉点,我不知道为什么。以下是我到目前为止的代码 -

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");
    }
}

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();

现在我已经设置了,所以 intersect 函数只记录到控制台,这样我就可以知道发生了什么。任何帮助都会很棒,因为我不确定自己做错了什么。

【问题讨论】:

    标签: javascript three.js collision-detection intersection bounding-box


    【解决方案1】:

    Box3.intersect

    .intersect ( box : Box3 ) : this box - 要与之相交的框。

    计算 this 和 box 的交集,将此框的上界设置为两个框的上界中较小的一个,并将此框的下界设置为两个框的下界中较大的一个。如果没有重叠,则将此框设为空。

    这个函数实际上是用来自boundingBoxPaddle 的信息更新boundingBoxBall,甚至可能将boundingBoxBall 设置为一个空框!

    我认为你真正追求的功能是:

    Box3.intersectsBox

    .intersectsBox ( box : Box3 ) : Boolean box - 检查交叉点的框。

    确定此框是否与框相交。

    intersectsBox 函数返回一个简单的true/false,因此您可以判断两个框是否碰撞。

    另请注意,您的边界框是相对于关联的几何图形的。如果您转换Mesh,那么您还需要转换边界框。 Box3 docs 上的示例代码实际上突出显示了这一点:

    const box = new THREE.Box3();
    
    // ...
    
    // in the animation loop, compute the current bounding box with the world matrix
    box.copy( mesh.geometry.boundingBox ).applyMatrix4( mesh.matrixWorld );
    

    完整示例:

    let W = window.innerWidth;
    let H = window.innerHeight;
    
    const renderer = new THREE.WebGLRenderer({
      antialias: true,
      alpha: true
    });
    document.body.appendChild(renderer.domElement);
    
    const scene = new THREE.Scene();
    
    const camera = new THREE.PerspectiveCamera(28, 1, 1, 1000);
    camera.position.set(0, 0, 50);
    camera.lookAt(scene.position);
    scene.add(camera);
    
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(0, 0, -1);
    camera.add(light);
    
    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 render() {
      renderer.render(scene, camera);
    }
    
    function resize() {
      W = window.innerWidth;
      H = window.innerHeight;
      renderer.setSize(W, H);
      camera.aspect = W / H;
      camera.updateProjectionMatrix();
      render();
    }
    
    let rate = 0.1;
    let goingRight = true;
    let ballBox = new THREE.Box3();
    let wallBox = new THREE.Box3();
    
    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);
    }
    
    window.addEventListener("resize", resize);
    
    resize();
    requestAnimationFrame(animate);
    html,
    body {
      width: 100%;
      height: 100%;
      padding: 0;
      margin: 0;
      overflow: hidden;
      background: skyblue;
    }
    &lt;script src="https://threejs.org/build/three.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 我仍然遇到的问题是,即使我使用 .intersectsBox 代替,即使边界框根本不相交,它也会继续不断地将交集记录到控制台。
    • @OliverCollier 我添加了一些可能有用的信息。您的边界框是其形状的局部,因此您必须更新它们以匹配形状的当前空间方向。
    • 尝试了您的建议,但没有成功。即使边界框完全分开,它仍然会不断地相交。我不知道我在这里做错了什么
    • @OliverCollier 我添加了一个完整的、可运行的示例,通过观察边界框的交叉点,球在两个框之间弹跳。如果您在查看此处的逻辑后仍然遇到问题,请使用更新后的代码更新您的问题,以便我们查看可能出现的问题。
    • 谢谢,我试试看
    猜你喜欢
    • 2015-08-27
    • 1970-01-01
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多