three.js中的碰撞墙

时间:2018-06-25 22:23:20

标签: javascript three.js collision-detection raycasting

我正在用three.js创建游戏。我是该领域的新手,但我已经阅读了很多碰撞文档。  我使用射线投射使立方体中包含的船与立方体中包含的岛之间发生碰撞。我试图通过这种方式解决问题。

collision2 = false;

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

            var ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
            var collisionResults = ray.intersectObjects( collidableMeshList );
            if ( collisionResults.length > 0 && collisionResults[0].distance < directionVector.length() ) {
                appendText(" Hit "),
                collision2 = true;
            }
}

    if ( keyboard.pressed("W") ){
        obj.translateZ( moveDistance ),
    if (collision2==true){
        obj.translateZ( -moveDistance*4 ),
        }
    }
    if ( keyboard.pressed("S") ){
        obj.translateZ( - moveDistance ),;
    if (collision2==true){
        obj.translateZ( moveDistance*4 ),
        }
    }
    if ( keyboard.pressed("A") ){
        obj.rotateOnAxis( new THREE.Vector3(0,1,0), rotateAngle),
    if (collision2==true){
        obj.rotateOnAxis( new THREE.Vector3(0,1,0), -rotateAngle*3),
        }
    }
    if ( keyboard.pressed("D") ){
        obj.rotateOnAxis( new THREE.Vector3(0,1,0), -rotateAngle),
    if (collision2==true){
        obj.rotateOnAxis( new THREE.Vector3(0,1,0), rotateAngle*3),
        }
    }    

乘以3“ moveDistance”和“ rotateAngle”,以免在碰撞过程中使我的船在射线猫发出的射线中坠毁。它通常可以工作,但有时船会卡住或进入岛屿。我曾考虑过要根据立方体的表面将飞船与岛屿碰撞时移动几个像素。示例:船在X轴正方向上与立方体的面碰撞,从立方体位置减去像素以使船移开。但是我不知道该怎么做,这对我来说是一个很好的解决方案。我该如何解决与墙壁碰撞的问题? (我现在不想使用任何物理引擎) 感谢那些会给我帮助的人!

screenshot

编辑:
我想指出立方体(岛屿)的哪一侧与飞船相撞。如果该面面向X轴(正),则将船形向后移动40个像素(obj.position = + 40),每个面都需要这样做。因此,您永远不能让船驶入立方体。我在看这个示例,我认为它可能是有用的,但是我还不知道如何解决它。
 https://stemkoski.github.io/Three.js/Mouse-Click.html

这是我的小船所在的立方体。

var mats2 = [];

    var cubeGeometry = new THREE.CubeGeometry(25,135,121,10,10,10);
    for (var i = 0; i < 6; i ++) {
    mats2.push(new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe:true } ));

}
    MovingCube = new THREE.Mesh( cubeGeometry, mats2 );
    scene.add( MovingCube );
    collidableMeshList0.push(MovingCube);

2 个答案:

答案 0 :(得分:1)

我认为我有很好的解决方法。
每次发生碰撞时,都会知道受影响的面孔。使用.face.normal。例如:如果碰撞的面是面向-x轴的面,则将具有:x:-1,y:0,z:0。如果碰撞的面是面向+ x轴的面,则将具有:x: +1,y:0,z:0。同样的原理适用于其他轴。所以我解决了以下方法。现在,小船不再卡在墙上了!

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

        var ray = new THREE.Raycaster( originPoint, directionVector.clone().normalize() );
         collisionResults1 = ray.intersectObjects( collidableMeshList );
        if ( collisionResults1.length > 0 && collisionResults1[0].distance < directionVector.length() ) {
            appendText(" Hit "),
            faccia = collisionResults1[0].face.normal;
            if (faccia.x <=-0.9 ){
                obj.position.x = originPoint.x -30,
            }
            if (faccia.x >=0.9 ){
                obj.position.x = originPoint.x +30,
            }
            if (faccia.z <=-0.9 ){,
                obj.position.z = originPoint.z -30,
            }
            if (faccia.z >=0.9 ){
                obj.position.z = originPoint.z +30,
            }

答案 1 :(得分:0)

有无数种方法可以完成用射线投射解决这个问题的方法。但是我做过的最有效的方法之一是制作一个简单的点质量系统,将三个点质量成三角形排列,并相互连接带有3个弹簧,并进行简单的Verlet样式仿真,以使其保持三角形配置。.然后,您通过获取该三角形的向量来重建对象矩阵,并组成一个正交基并将其插入您的three.js对象。然后在每帧中,对点质量施加重力,如果它们在海平面以下,则施加与点在海平面以下深度成比例的任意浮力。然后,对于每个点质量,从点中心向下进行射线投射,并调整点质量位置,以保持与高度图的地面高度的距离。

这是我很久以前制作的类似产品的原型: http://vectorslave.com/webgl/zbox.html(用ASWD +箭头键控制斩波器)