gpt4 book ai didi

javascript - 使用 Three.js 进行碰撞检测

转载 作者:行者123 更新时间:2023-12-02 23:43:51 26 4
gpt4 key购买 nike

我用 Three.js 创建了一个非常简单的世界。我正在制作一个非常基本的平台,并且当用户在硬币上运行时,我试图让碰撞检测起作用,以更新已触摸了多少硬币的文本计数器。截至目前,当我运行硬币时,没有任何反应,也没有 JavaScript 控制台错误。任何帮助都会很棒。

我一直在尝试使用光线转换器来检测碰撞。这是我所拥有的一些片段,如果需要,我可以转储更多或全部 600 行左右的代码。”

<div id="info">
<h1 style="color: white">0/10</h1>
</div>

Javascript:

var coin = [];
var raycaster;
var loader = new THREE.GLTFLoader();
... //Lots more variables I've left out for readability


initThree();
initCannon();
animate();

function initThree() {

clock = new THREE.Clock();

//Renderer
var width = window.innerWidth;
var height = window.innerHeight;

renderer = new THREE.WebGLRenderer( {antialias: true} );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( width, height );
document.body.appendChild( renderer.domElement );

scene = new THREE.Scene();
scene.background = new THREE.Color( 0xb2b2b2 );
scene.fog = new THREE.Fog( 0x9bacc6, 0, 7000 );

//Camera
camera = new THREE.PerspectiveCamera( 90, width/height, 1, 10000 );
//camera.position.set( 3000, 3000, 3000 );
camera.position.set( 0, 10, 0 );
camera.lookAt( scene.position );

//Controls
controls = new THREE.PointerLockControls( camera );

var blocker = document.getElementById( 'blocker' );
var instructions = document.getElementById( 'instructions' );

//Lock control when focused
instructions.addEventListener( 'click', function () {

controls.lock();

}, false );

//Hide overlay
controls.addEventListener( 'lock', function () {

instructions.style.display = 'none';
blocker.style.display = 'none';

} );

controls.addEventListener( 'unlock', function () {

blocker.style.display = 'block';
instructions.style.display = '';

} );
scene.add( controls.getObject() );

//Raycaster
raycaster = new THREE.Raycaster( new THREE.Vector3(), new THREE.Vector3( 0, -1, 0 ), 0, 10 );

loadTrees();
loadCoins();
createLight();
createGround();
createWater();
createSky();
}

function loadCoins() {

var coinPath = '../models/gltf/coin/scene.gltf';
loader.load( coinPath, function( gltf ) {
coin[0] = gltf.scene;
coin[0].position.set(3300,1500,1000);
coin[0].scale.set(100,100,100);
scene.add( coin[0] );
});
loader.load( coinPath, function( gltf ) {
coin[1] = gltf.scene;
coin[1].position.set(3300,1500,-1000);
coin[1].scale.set(100,100,100);
scene.add( coin[1] );
...
});

function animate() {
requestAnimationFrame( animate );
update();
render();
}

function update() {
//controls.update();

world.step( timeStep );

ground.position.copy( groundBody.position );
ground.quaternion.copy( groundBody.quaternion );

var mixDelta = clock.getDelta();
if( mixer != null) {
mixer.update( mixDelta );
mixer2.update( mixDelta );
mixer3.update( mixDelta );
}

raycaster.ray.origin.copy( controls.getObject().position );
raycaster.ray.origin.y -= 100;

//checks to see if intersecting object array
var intersections = raycaster.intersectObjects( coin );

var touching = intersections.length > 0;

var time = performance.now();
var delta = ( time - prevTime ) / 1000;

velocity.x -= velocity.x * 10 * delta;
velocity.z -= velocity.z * 10 * delta;
velocity.y -= 9.8 * 100 * delta; //100 = mass //9.8

direction.z = Number( moveForward ) - Number( moveBackward );
direction.x = Number( moveLeft ) - Number( moveRight );
direction.normalize(); //consistent movement in all directions

if( moveForward || moveBackward ) {
velocity.z -= direction.z * 7500 * delta;
}
if( moveLeft || moveRight ) {
velocity.x -= direction.x * 7500 * delta;
}

//Stops when runs into an object
if ( touching === true ) {
coinCount += 1;
document.getElementById('info').innerHTML = coinCount + "/10";
}


controls.getObject().translateX( velocity.x * delta );
controls.getObject().translateY( velocity.y * delta );
controls.getObject().translateZ( velocity.z * delta );

//Keep Player within bounds of game
if ( controls.getObject().position.y < 200 ) {

velocity.y = 0;
controls.getObject().position.y = 200;

canJump = true;

}
if ( controls.getObject().position.x < -4000 ) {
velocity.x = 0;
controls.getObject().position.x = -4000;
}
if ( controls.getObject().position.x > 4000 ) {
velocity.x = 0;
controls.getObject().position.x = 4000;
}
if ( controls.getObject().position.z < -4000 ) {
velocity.x = 0;
controls.getObject().position.z = -4000;
}
if ( controls.getObject().position.z > 4000 ) {
velocity.x = 0;
controls.getObject().position.z = 4000;
}

prevTime = time;

//Update Water
water.material.uniforms[ "time" ].value += 1.0 / 60.0;

//Spin Coins
for( i=0; i<coin.length; i++ ) {
coin[i].rotation.y += .05;
}
}

最佳答案

光线转换对于该用例来说并不是理想的碰撞检测方法。考虑用简单的边界体积来表示您的硬币,例如 THREE.Box3 (AABB)或THREE.Sphere (边界球)。玩家本身也将用这样的包围体来表示。然后,在动画循环中,您可以测试玩家的边界体积是否与游戏环境中的某些对象(例如硬币)相交。这是比使用单条射线更可靠的测试,因为您可以更好地表示具有空间扩展的 3D 对象。

顺便说一句:如果您还不熟悉包围体,我强烈建议您稍微研究一下这个主题。 AABB 和边界球是碰撞检测中非常重要的实体。一个很好的资源是 Fletcher Dunn Ian Parberry 所著的《3D Math Primer for Graphics and Game Development》,第 9 章几何基元

关于javascript - 使用 Three.js 进行碰撞检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55942235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com