Столкновение стен в тройке - PullRequest
0 голосов
/ 26 июня 2018

Я создаю игру в three.js.Я новичок в этой области, но я прочитал много документации о столкновениях.Я использовал raycast, чтобы получить столкновение между моей лодкой, содержащейся в кубе, и островами, содержащимися в кубах.Я попытался решить проблему следующим образом.

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", чтобы не разбить мой корабль лучами, испущенными raycat во время столкновения.Это часто работает, но иногда корабль застревает или входит в остров.Я думал о перемещении корабля на несколько пикселей, когда он сталкивается с островом на основании грани куба.Пример: корабль сталкивается с гранью куба на положительной оси 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 голосов
/ 27 июня 2018

Думаю, у меня есть хорошее решение.
Каждый раз, когда происходит столкновение, можно узнать лицо, на которое оно попало.Использование .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,
            }
0 голосов
/ 26 июня 2018

Существует бесконечное множество способов решить эту проблему с помощью радиопередач, но одна из самых эффективных работ, которые я сделал, - создать простую систему точечных масс с 3 точечными массами, расположенными в треугольнике, соединенном между собой.с 3 пружинами и выполните простое моделирование стиля верлета, чтобы сохранить их в треугольной конфигурации. Затем вы воссоздаете матрицу объекта, беря векторы этого треугольника, и составляете ортонормированный базис и вставляете его в свой объект three.js.Затем в каждом кадре вы применяете гравитационную силу к своим точечным массам, а если они находятся ниже уровня моря, применяете произвольную силу плавучести, пропорциональную глубине точек ниже уровня моря.Затем для каждой точечной массы вы совершаете радиопередачу вниз от центра точки и настраиваете положение точечных масс, чтобы сохранить расстояние от высоты земли вашей карты высот.

Вот прототип чего-то подобного, который я сделалдавно: http://vectorslave.com/webgl/zbox.html (ASWD + клавиши со стрелками для управления прерывателем)

...