这是我的第一个三个 js 第一人称视角游戏,当我转动相机时遇到问题,枪不跟随我正在看的相机旋转。
这是现场网站的链接:https : //geniussniper.github.io/Glory/ 按下 0 将显示相机旋转和枪位按下 y 可以控制环顾“asdw”以进行移动
这是我的代码
import * as THREE from 'three';
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
class World {
constructor(){
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
this.clock = new THREE.Clock();
this.world = {
player: {
x: 0, // a,d side way control
y: 30, // flying cheating control
z: 0, // w,s forward backward control
// canShoot: 0,
},
movementSpeed: .4,
size: 1000,
camera: {
y: 10
},
bullets: [],
timer: 0
}
this.renderer = new THREE.WebGLRenderer({
antialias: true
});
this.hemisphereLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 1 );
this.scene.add( this.hemisphereLight );
this.directionalLight = new THREE.DirectionalLight(0xffffff)
this.scene.add(this.directionalLight);
this.keyborad = [];
addEventListener('keydown', e => {
this.keyborad[e.key] = true;
});
addEventListener('keyup', e => {
this.keyborad[e.key] = false;
});
addEventListener( 'click', () => {
if(this.pistol){
let bullet = new THREE.Mesh(
new THREE.SphereGeometry(0.05, 8, 8),
new THREE.MeshBasicMaterial({color: 0xffffff})
);
bullet.position.set(
this.pistol.position.x,
this.pistol.position.y + 0.4,
this.pistol.position.z
)
bullet.velocity = new THREE.Vector3(
-Math.sin(this.camera.rotation.y),
0,
Math.cos(this.camera.rotation.y)
);
bullet.alive = true;
setTimeout(() => {
bullet.alive = false;
this.scene.remove(bullet);
}, 1000);
this.world.bullets.push(bullet);
this.scene.add(bullet);
}
}, false );
this.loader = new GLTFLoader();
this.render();
}
animate() {
requestAnimationFrame( () => this.animate() );
this.processKeyboard();
// this.controls.update(); //OrbitControls for not following charater
this.shotting();
this.renderer.render( this.scene, this.camera );
}
shotting() {
for( let i = 0; i < this.world.bullets.length; i++){
if(this.world.bullets[i] === undefined) continue;
if(this.world.bullets[i].alive === false){
this.world.bullets.splice(i, 1);
continue;
}
this.world.bullets[i].position.add(this.world.bullets[i].velocity);
}
}
worldSetup() {
this.renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( this.renderer.domElement );
this.camera.position.setY(10);
this.camera.position.setZ(30);
// this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls = new PointerLockControls(this.camera, this.renderer.domElement);
this.loader.load('./src/models/game_pirate_adventure_map/scene.gltf', (gltf) => {
gltf.scene.scale.set(0.01, 0.01, 0.01);
this.scene.add(gltf.scene);
});
this.loader.load('./src/models/vis_p35p_pistol/scene.gltf', (gltf) => {
gltf.scene.scale.set(0.01, 0.01, 0.01);
gltf.scene.position.set(0, 8, 34);
this.pistol = gltf.scene;
this.scene.add(this.pistol);
});
window.addEventListener( 'resize', () => {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
}
processKeyboard() {
let time = Date.now() * 0.0005;
if(this.keyborad['w']){
this.controls.moveForward(this.world.movementSpeed);
}
if(this.keyborad['s']) {
this.controls.moveForward(-this.world.movementSpeed);
}
if(this.keyborad['a']){
this.controls.moveRight(-this.world.movementSpeed);
}
if(this.keyborad['d']) {
this.controls.moveRight(this.world.movementSpeed);
}
if(this.keyborad['y']){
this.controls.lock();
}
if(this.keyborad['esc']) {
this.controls.unlock();
}
if(this.keyborad['0']){
//the debugging console
if(this.world.timer <= 0){
// console.log(this.camera.position);
console.log(this.camera.rotation);
console.log(this.pistol.position);
// console.log(this.pistol.rotation);
this.world.timer = 10;
} else {
this.world.timer -= 1;
}
}
if(this.pistol){
let rotation = this.camera.rotation.y + Math.PI/6
this.pistol.position.set(
this.camera.position.x - Math.sin(rotation) * 4,
this.camera.position.y - 1 + Math.sin(time * 4 + this.camera.position.x + this.camera.position.z) * 0.04,
this.camera.position.z + Math.cos(rotation) * 4
)
this.pistol.rotation.set(
this.camera.rotation.x,
this.camera.rotation.y - Math.PI/2,
this.camera.rotation.z
)
}
}
render() {
this.worldSetup();
this.camera.lookAt(new THREE.Vector3(0, this.world.camera.y, 40))
this.animate();
};
}
export default World;