我试图在没有 div 的情况下遵循https://threejs.org/examples/misc_controls_pointerlock.html上的源代码,但它没有用。然后我尝试按照这里的代码https://sbcode.net/threejs/pointerlock-controls/但它也没有工作。
对于第一人称视图,我只是希望能够使用指针锁定控件环顾四周。之后我将能够理清控件的移动。
目前我有一个模型(mainChar),相机连接在他身上。我希望指针锁定控件以某种方式附加到他的位置。
这是我的代码不起作用:
//IMPORT STATEMENTS
import { EntityManager } from './EntityManager.js';
import { LightingManager } from './LightingManager.js';
import { Time } from '../Time.js';
import { PauseMenu } from '../SceneSubjects/Menu/PauseMenu.js';
import { keyboardManager } from './KeyboardManager.js';
//lights
import { GeneralLights } from '../SceneSubjects/lighting/GeneralLights.js';
import { CeilingLight } from '../SceneSubjects/lighting/CeilingLight.js';
import { CeilingLightObj } from '../SceneSubjects/objects/CeilingLightObj.js';
//objects
import { House } from '../SceneSubjects/House.js';
import { SceneSubject } from '../SceneSubjects/objects/SceneSubject.js';
import { TestBlock } from '../SceneSubjects/characters/TestBlock.js';
import { Door } from '../SceneSubjects/objects/Door.js';
import { MainChar } from '../SceneSubjects/characters/MainChar.js';
//other
import { PointerLockControls } from '../../jsm/PointerLockControls.js';
import { OrbitControls } from '../../jsm/OrbitControls.js';
import * as THREE from '../../../jsm/three.module.js';
//==================================================================================================
//Global Variables
//lights
var generalLights = new GeneralLights();
//ceiling lights
var bedroomLightObj = new CeilingLightObj();
var kitchenLightObj = new CeilingLightObj();
var studyLightObj = new CeilingLightObj();
var hallwayLightObj1 = new CeilingLightObj();
var hallwayLightObj2 = new CeilingLightObj();
var bathroomLightObj = new CeilingLightObj();
var loungeLightObj = new CeilingLightObj();
var bedroomLight = new CeilingLight();
var kitchenLight = new CeilingLight();
var studyLight = new CeilingLight();
var hallwayLight1 = new CeilingLight();
var bathroomLight = new CeilingLight();
var hallwayLight2 = new CeilingLight();
var loungeLight = new CeilingLight();
//objects
var house = new House();
var sceneSubject = new SceneSubject();
var testBlock = new TestBlock();
var testdoor = new Door();
export var mainChar = new MainChar(testBlock);
export class SceneManager {
constructor(canvas) {
//this entire function renders a scene where you can add as many items as you want to it (e.g. we can create the house and add as
//many items as we want to the house). It renders objects from other javascript files
//------------------------------------------------------------------------------------------------------------------------------------------
//These are supposed to act like constants. DO NOT CHANGE
this.GAME_PAUSE = "pause";
this.GAME_RUN = "run";
this.GAME_START = "start";
//------------------------------------------------------------------------------------------------------------------------------------------
//we use (this) to make variables accessible in other classes
this.time = new Time();
this.objPauseMenu;
this.game_state = this.GAME_RUN;
this.width_screen = canvas.width;
this.height_screen = canvas.height;
this.screenDimensions = {
width: canvas.width,
height: canvas.height
};
//the essentials for rendering a scene
this.scene = this.buildScene();
this.renderer = this.buildRender(this.screenDimensions);
this.camera = this.buildCamera(this.screenDimensions);
//comment this out
// this.controls = new OrbitControls(this.camera, this.renderer.domElement);
//initialise pointerlock controls
this.pointerLockControls = new PointerLockControls(this.camera, this.renderer.domElement);
this.pointerLockControls.unlock();
//this.scene.add(this.pointerLockControls.getObject());
//====================
//adjust the ceiling light properties in the house
this.setCeilingLightProperties();
this.managers = this.createManagers();
//load things to scene
this.loadToScene(this.managers[0].lights);
this.loadToScene(this.managers[1].entities);
//---------------------------------------------------------------------------------------------------------------------------------
// Ok, now we have the cube. Next we'll create the hud. For that we'll
// need a separate scene which we'll render on top of our 3D scene. We'll
// use a dynamic texture to render the HUD.
// We will use 2D canvas element to render our HUD.
//---------------------------------------------------------------------------------------------------------------------------------
}
loadToScene(entities) {
for (let i = 0; i < entities.length; i++) {
this.scene.add(entities[i].object);
}
}
//this function creates our scene
buildScene() {
//create a new scene
const scene = new THREE.Scene();
//set the scene's background-> in this case it is our skybox
const loader = new THREE.CubeTextureLoader();
//it uses different textures per face of cube
const texture = loader.load([
'../skybox/House/posx.jpg',
'../skybox/House/negx.jpg',
'../skybox/House/posy.jpg',
'../skybox/House/negy.jpg',
'../skybox/House/posz.jpg',
'../skybox/House/negz.jpg'
]);
scene.background = texture;
//if we wanted it to be a colour, it would have been this commented code:
//scene.background = new THREE.Color("#000");
return scene;
}
//this creates a renderer for us
buildRender({ width, height }) {
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true, alpha: true
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
return renderer;
}
//create a camera for the screen
buildCamera({ width, height }) {
//SETTING FIELD OF VIEW, ASPECT RATIO (which should generally be width/ height), NEAR AND FAR (anything outside near/ far is clipped)
const aspectRatio = width / height;
const fieldOfView = 60;
const nearPlane = 1;
const farPlane = 1000;
//there are 2 types of cameras: orthographic and perspective- we will use perspective (more realistic)
const camera = new THREE.PerspectiveCamera(fieldOfView, aspectRatio, nearPlane, farPlane);
//Set camera initial position to main character
let pos = mainChar.returnWorldPosition();
camera.position.set(pos.x, pos.y + 10, pos.z - 10);
return camera;
}
setCeilingLightProperties() {
//set their light positions
bedroomLightObj.setLightPosition(0, 21, 50);
bedroomLight.setLightPosition(0, 16, 50);
loungeLightObj.setLightPosition(-45, 21, -60);
loungeLight.setLightPosition(-45, 16, -60);
studyLightObj.setLightPosition(35, 21, -50);
studyLight.setLightPosition(35, 16, -50);
kitchenLight.setLightPosition(-45, 16, 5);
kitchenLightObj.setLightPosition(-45, 21, 5);
bathroomLight.setLightPosition(45, 16, 15);
bathroomLightObj.setLightPosition(45, 21, 15);
hallwayLightObj1.setLightPosition(0, 21, -60);
hallwayLight1.setLightPosition(0, 16, -60);
hallwayLightObj2.setLightPosition(0, 21, 0);
hallwayLight2.setLightPosition(0, 16, 0);
}
//add subjects to the scene
createManagers() {
const managers = [new LightingManager(), new EntityManager()];
//can be altered so we can add multiple entities, and depending on which position
//it is, certain ones won't be paused, and some will be
//Note that these variables are declared globally before the class definition
/*This is so that we can use any of these object's methods or values later somewhere else*/
//lights
// managers[0].register(generalLights);
managers[0].register(bedroomLight);
managers[0].register(loungeLight);
managers[0].register(studyLight);
managers[0].register(hallwayLight1);
managers[0].register(hallwayLight2);
managers[0].register(kitchenLight);
managers[0].register(bathroomLight);
//entities
managers[1].register(loungeLightObj);
managers[1].register(studyLightObj);
managers[1].register(kitchenLightObj);
managers[1].register(bathroomLightObj);
managers[1].register(bedroomLightObj);
managers[1].register(hallwayLightObj1);
managers[1].register(hallwayLightObj2);
managers[1].register(house);
testdoor.setPosition(0, -0.5, 33);
//testdoor.setRotation(-Math.PI/2);
managers[1].register(testdoor);
managers[1].register(mainChar);
managers[1].register(sceneSubject);
managers[1].register(testBlock);
return managers;
}
updateCameraPosition() {
//Match camera position and direction to the character's position and direction
let pos = mainChar.returnWorldPosition();
let dir = mainChar.returnObjectDirection();
//Set y to 10 to move camera closer to head-height
//UNCOMMENT FOR 3RD PERSON
// this.camera.position.set(pos.x, 10 +10, pos.z + 20);
// this.camera.rotation.set(dir.x - 0.5, dir.y, dir.z);
//UNCOMMENT FOR FIRST PERSON
this.camera.position.set(pos.x, 15, pos.z - 5);
this.camera.rotation.set(dir.x, dir.y, dir.z);
}
//this updates the subject/model every frame
update() {
//won't call this loop if it's paused-> only for objects that need to be paused (managers that need to be paused)
if (this.game_state == this.GAME_RUN) {
//TO EXPERIMENT WITH FOR LOOKING AROUND!
// this.camera.position.x += ( keyboardManager.getMouseX() - this.camera.position.x ) ;
// this.camera.position.y += ( - keyboardManager.getMouseY() - this.camera.position.y );
// this.camera.lookAt( this.scene.position );
const runTime = this.time.getRunTime();
this.managers[0].update(runTime);
this.managers[1].update(runTime);
//update orbit controls
//comment out this.controls.update()
//this.controls.update();
this.renderer.render(this.scene, this.camera);
}
else {
//comment out
// this.controls.update();
this.renderer.autoClear = true;
//render scene1
this.renderer.render(this.scene, this.camera);
//prevent canvas from being erased with next .render call
this.renderer.autoClear = false;
//just render scene2 on top of scene1
this.renderer.render(this.objPauseMenu.scene, this.objPauseMenu.camera);
// renderer.autoClear = true;
}
//update orbit controls
//comment out
// this.controls.update();
//uncomment this
this.updateCameraPosition();
}
//this resizes our game when screen size changed
onWindowResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
pause() { //when pause mode is entered. The pause menu needs to be rendered.
this.game_state = this.GAME_PAUSE;
this.time.pause();
//comment out
// this.controls.enabled = false; // stop orbit controls from responding to use input
this.objPauseMenu = new PauseMenu(this.width_screen, this.height_screen);
}
unpause() {
this.game_state = this.GAME_RUN;
this.time.unpause();
//comment out
// this.controls.enabled = true; // start orbit controls tp respond to input
}
}