我正在尝试使用 Three.js“射击”子弹/射弹:
let renderer, camera, scene, light, plane, cube, spheres;
initialize();
animate();
function initialize() {
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight);
scene = new THREE.Scene();
light = new THREE.SpotLight("#ffffff");
light.position.y = 700;
scene.add(light);
plane = new THREE.Mesh();
plane.material = new THREE.MeshToonMaterial({ color: "#0000ff" });
plane.geometry = new THREE.PlaneGeometry(60, 30);
plane.position.z = -50;
scene.add(plane);
cube = new THREE.Mesh();
cube.material = new THREE.MeshToonMaterial({ color: "#ff0000", transparent: true, opacity: 0.85 });
cube.geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
cube.position.y = -1;
cube.position.z = -3;
scene.add(cube);
spheres = [];
window.addEventListener("click", event => {
let mouse2d = getMouse2D(event.clientX, event.clientY);
let mouse3d = getMouse3D(mouse2d, plane.position.z);
shoot(mouse3d);
}, false);
}
function animate() {
spheres.forEach(sphere => {
// TODO: Update sphere position based on sphere.userData.target
sphere.position.z -= 1;
});
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function shoot(target) {
let sphere = new THREE.Mesh();
sphere.material = new THREE.MeshToonMaterial({ color: "#00ff00" });
sphere.geometry = new THREE.SphereGeometry(0.25);
sphere.position.x = cube.position.x;
sphere.position.y = cube.position.y;
sphere.position.z = cube.position.z;
sphere.userData.target = target;
scene.add(sphere);
spheres.push(sphere);
}
function getMouse3D(mouse2d, z) {
let vector = new THREE.Vector3(mouse2d.x, mouse2d.y);
vector.unproject(camera);
let dir = vector.sub(camera.position).normalize();
let distance = (z - camera.position.z) / dir.z;
return camera.position.clone().add(dir.multiplyScalar(distance));
}
function getMouse2D(x, y) {
return new THREE.Vector2(
(x / renderer.domElement.clientWidth) * 2 - 1,
-(y / renderer.domElement.clientHeight) * 2 + 1
);
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: 0;
background: #eeeeee;
}
canvas {
display: block;
cursor: crosshair;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.js">
</script>
正如您所看到的,单击鼠标时,球体会从立方体发射到平面。
我已经写了getMouse3D()
函数来确定用户单击的平面上的位置,当生成球体时,我将其存储在 sphere.userData.target
中。但我不知道如何更新每帧球体的位置,以便它朝它移动(请参阅 TODO
评论)。换句话说,当球体到达平面时,它应该与平面相交于sphere.userData.target
。 (用户点击的位置)。
我该怎么做?
最佳答案
你知道立方体的位置,你知道最终位置(目标),所以你可以计算方向,并将其乘以速度:
sphere.position.addScaledVector(sphere.userData.direction, sphere.userData.speed * delta);
if (sphere.position.z <= plane.position.z) sphere.userData.speed = 0; // stop, when we reached the plane
我用 THREE.Raycaster()
重新编写了您的代码以获取目标的位置(它简化了代码,因此您可以摆脱 getMouse3D()
并getMouse2D()
函数)。
let renderer, camera, scene, light, plane, cube, spheres, raycaster = new THREE.Raycaster(), mouse = new THREE.Vector2(), intersects, clock = new THREE.Clock(), delta = 0;
initialize();
animate();
function initialize() {
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight);
scene = new THREE.Scene();
light = new THREE.SpotLight("#ffffff");
light.position.y = 700;
scene.add(light);
plane = new THREE.Mesh();
plane.material = new THREE.MeshToonMaterial({ color: "#0000ff" });
plane.geometry = new THREE.PlaneGeometry(60, 30);
plane.position.z = -50;
scene.add(plane);
cube = new THREE.Mesh();
cube.material = new THREE.MeshToonMaterial({ color: "#ff0000", transparent: true, opacity: 0.85 });
cube.geometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
cube.position.y = -1;
cube.position.z = -3;
scene.add(cube);
spheres = [];
window.addEventListener("click", event => {
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
intersects = raycaster.intersectObjects([plane]);
if (intersects.length == 0) return;
shoot(intersects[0].point);
}, false);
}
function animate() {
delta = clock.getDelta();
spheres.forEach(sphere => {
sphere.position.addScaledVector(sphere.userData.direction, sphere.userData.speed * delta);
if (sphere.position.z <= plane.position.z) sphere.userData.speed = 0; // stop, when we reached the plane
});
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function shoot(target) {
let sphere = new THREE.Mesh();
sphere.material = new THREE.MeshToonMaterial({ color: "#00ff00" });
sphere.geometry = new THREE.SphereGeometry(0.5);
sphere.position.copy(cube.position);
sphere.userData.direction = target.sub(cube.position).normalize();
sphere.userData.speed = 20;
scene.add(sphere);
spheres.push(sphere);
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
border: 0;
background: #eeeeee;
}
canvas {
display: block;
cursor: crosshair;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.js">
</script>
关于javascript - 将对象移动到某个位置 ( Three.js ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46648461/