0

レンダー ループで呼び出されて衝突を検出し、プレーヤー/カメラを移動するこの関数を作成しました (これは一人称ゲームです)。衝突はpCube、フレームごとにカメラに一致するように移動されるという名前の CubeGeometry を使用して検出されます。

// Player movements
function pMovements() {
    mPlayer.colBottom = false;

    pCube.position.x = mPlayer.yawObject.position.x + 50; // The cube is placed +50 so we can see/debug it.
    pCube.position.y = mPlayer.yawObject.position.y - 10;
    pCube.position.z = mPlayer.yawObject.position.z;

    // -- COLLISION DETECTION START --
    var originPoint = pCube.position.clone();

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

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

            // Bottom vertices
            if (vertexIndex == 2 || vertexIndex == 3 || vertexIndex == 6 || vertexIndex == 7) {
                mPlayer.colBottom = true;
                mPlayer.velocity.y = Math.max( 0, mPlayer.velocity.y ); // Stop falling
            }
        }
    }
    // -- COLLISION DETECTION END --

    var delta = (Date.now() - time) * 0.1;

    mPlayer.velocity.x += (-mPlayer.velocity.x) * 0.08 * delta; // walking
    mPlayer.velocity.z += (-mPlayer.velocity.z) * 0.08 * delta; // walking
    if (mPlayer.colBottom == false) {
        mPlayer.velocity.y -= 0.1 * delta; // falling
    }

    if (mPlayer.moveForward) mPlayer.velocity.z -= mPlayer.speed * delta;
    if (mPlayer.moveBack) mPlayer.velocity.z += mPlayer.speed * delta;
    if (mPlayer.moveLeft) mPlayer.velocity.x -= mPlayer.speed * delta;
    if (mPlayer.moveRight) mPlayer.velocity.x += mPlayer.speed * delta;

    mPlayer.yawObject.translateX(mPlayer.velocity.x);
    mPlayer.yawObject.translateY(mPlayer.velocity.y); 
    mPlayer.yawObject.translateZ(mPlayer.velocity.z);

    if (mPlayer.yawObject.position.y < -2000) {
        // Player has fallen out of bounds :( so re-initialise the players position
        mPlayer.velocity.y = 0;
        mPlayer.yawObject.position.y = 100;
        mPlayer.yawObject.position.x = 0;
        mPlayer.yawObject.position.z = 0;

        mPlayer.yawObject.rotation.y = 0;
        mPlayer.pitchObject.rotation.x = 0;
    }

    if (mPlayer.moveDown) {
        mPlayer.yawObject.position.y -= 1;
    }
    if (mPlayer.moveUp) {
        mPlayer.yawObject.position.y += 1;
    }
}

デモについては、ここをクリックしてください。
動くWASD。ジャンプするスペース(一種)。黒い立方体/長方形は、x 軸上のカメラ位置 +50 を反映しています。立方体で衝突が検出されます。

基本的に、これについて2つの質問があります。立方体の頂点を使用して衝突を検出する必要がありますか?それとも面を検出する必要がありますか? オブジェクトが立方体よりも小さい場合、頂点に衝突しないため、衝突は検出されません。では、代わりに顔用に書き直す必要がありますか?

次に、衝突が検出されたときに立方体が下に落ちすぎないようにするにはどうすればよいですか。デモを確認すると、立方体が何かから落ちるたびに、止まる前にしばらく落ち続けます。何か関係があると思いますmPlayer.velocity.yが、修正できませんでした。ジャンプしても、立方体は床の奥まで沈みます。

4

1 に答える 1

1

衝突検出の「解像度」を上げるには、たとえば pCube を宣言するときに、キューブに頂点を追加します。

pCube = new THREE.CubeGeometry(100,100,100, 5,5,5);

コードの残りの部分は変更されない可能性があります。

衝突検出用に作成された光線の「間をすり抜ける」小さなオブジェクトに関しては、一般に、この方法を使用して小さなオブジェクトに光線を作成させると、衝突をより正確に検出できます。

于 2013-03-28T03:52:15.373 に答える