advanced character controls + zoom/fov

This commit is contained in:
2025-11-30 09:42:29 +02:00
parent 4e008e6ccd
commit 14772a039c
5 changed files with 62 additions and 30 deletions
@@ -1,5 +1,4 @@
import { TextureLoader, MeshStandardMaterial, MeshBasicMaterial, PlaneGeometry, Mesh, DoubleSide, Vector3 } from "three"; import { TextureLoader, MeshStandardMaterial, MeshBasicMaterial, PlaneGeometry, Mesh, DoubleSide, Vector3 } from "three";
import { assignParams } from "@/lib/MeshUtils";
class ImageObject { class ImageObject {
constructor(engine, obj) { constructor(engine, obj) {
+7 -6
View File
@@ -61,7 +61,7 @@ class DashBoard {
); );
const loadingProgress = new ProgressBar(engine); const loadingProgress = new ProgressBar(engine);
loadingProgress.object.scale.set(engine.aspect*0.8, 0.05, 0.05) loadingProgress.object.scale.set(engine.aspect*0.8, 0.05, 0.05)
loadingProgress.object.position.set(-engine.aspect/2 + engine.aspect*0.1, 0, 0.1) loadingProgress.object.position.set(-engine.aspect/2 + engine.aspect*0.1, 0, 0)
loadingPlane.add(loadingProgress.object); loadingPlane.add(loadingProgress.object);
dash.add(loadingPlane); dash.add(loadingPlane);
@@ -74,7 +74,7 @@ class DashBoard {
transparent:true transparent:true
}) })
); );
hudPlane.position.z = -0.22; hudPlane.position.z = 0;
hudPlane.position.y = -0.05 hudPlane.position.y = -0.05
hud.add(hudPlane) hud.add(hudPlane)
@@ -86,8 +86,8 @@ class DashBoard {
transparent:true transparent:true
}) })
); );
textPlane.position.z = -0.25; textPlane.position.z = -0.002;
textPlane.position.y = -0.46 textPlane.position.y = -0.41
textPlane.visible = false; textPlane.visible = false;
dash.add(textPlane) dash.add(textPlane)
})() })()
@@ -115,7 +115,8 @@ class DashBoard {
engine.addEventListener('beforeRender', ()=>{ engine.addEventListener('beforeRender', ()=>{
dash.quaternion.copy(engine.camera.quaternion) dash.quaternion.copy(engine.camera.quaternion)
dash.position.copy(engine.camera.position) dash.position.copy(engine.camera.position)
dash.translateZ(-1.2 * engine.camera.zoom); //dash.translateZ(-1.2 * engine.camera.zoom);
dash.translateZ(-0.5/Math.tan(engine.camera.fov/2 * Math.PI/180) * engine.camera.zoom);
}) })
this.updateText = function(t, textScrolledCallback){ this.updateText = function(t, textScrolledCallback){
@@ -147,7 +148,7 @@ class DashBoard {
levelProgress = new ProgressBar(engine) levelProgress = new ProgressBar(engine)
dash.add(levelProgress.object); dash.add(levelProgress.object);
levelProgress.object.position.set(-engine.aspect/2 + engine.aspect/30, 0.45, -0.01) levelProgress.object.position.set(-engine.aspect/2 + engine.aspect/30, 0.45, -0.001)
levelProgress.object.scale.set(engine.aspect/3, 0.02, 0.02) levelProgress.object.scale.set(engine.aspect/3, 0.02, 0.02)
this.levelProgress = levelProgress; this.levelProgress = levelProgress;
+8 -2
View File
@@ -126,7 +126,7 @@ class GameEngine extends THREE.EventDispatcher{
} }
this.orbitControls = controls; this.orbitControls = controls;
//controls.enableZoom = true; controls.enableZoom = false;
//const controls = new MapControls( camera, renderer.domElement ); //const controls = new MapControls( camera, renderer.domElement );
this.transformControls = new TransformControls(this.camera, renderer.domElement); this.transformControls = new TransformControls(this.camera, renderer.domElement);
this.transformControls.addEventListener('dragging-changed', function (event) { this.transformControls.addEventListener('dragging-changed', function (event) {
@@ -179,7 +179,13 @@ class GameEngine extends THREE.EventDispatcher{
//console.log('GameEngine started') //console.log('GameEngine started')
renderer.domElement.addEventListener('wheel', (event) => { renderer.domElement.addEventListener('wheel', (event) => {
if (gameEngine.hero){ if (gameEngine.hero){
gameEngine.hero.cameraZ += event.deltaY / 100; if (!gameEngine.hero.pointerControls.controls.isLocked){
gameEngine.hero.cameraZ += event.deltaY / 100;
}else{
gameEngine.camera.fov += event.deltaY / 100;
gameEngine.camera.fov = Math.min(Math.max(gameEngine.camera.fov, 0.01), 90);
gameEngine.camera.updateProjectionMatrix();
}
}else{ }else{
gameEngine.camera.zoom -= event.deltaY / 1000; gameEngine.camera.zoom -= event.deltaY / 1000;
gameEngine.camera.zoom = Math.max(gameEngine.camera.zoom, .4); gameEngine.camera.zoom = Math.max(gameEngine.camera.zoom, .4);
+47 -20
View File
@@ -13,7 +13,11 @@ class Hero{
} }
set cameraZ(v){ set cameraZ(v){
this.#cameraZ = Math.min(Math.max(v, 2), 10); this.#cameraZ = Math.min(Math.max(v, 1), 10);
if (this.#cameraZ == 1){
this.#cameraZ = 0;
this.lockControls();
}
} }
fadeDuration = 0.2 fadeDuration = 0.2
@@ -75,7 +79,7 @@ class Hero{
this.cameraY = this.size.y * 1.5; this.cameraY = this.size.y * 1.5;
this.direction = this.model.rotation.y; this.direction = this.model.rotation.y;
this.directionVelocity = 0; //this.directionVelocity = 0;
this.actionStart = 0; this.actionStart = 0;
this.cameraDelta = 0; this.cameraDelta = 0;
this.cameraIdleDelta = 0; this.cameraIdleDelta = 0;
@@ -100,11 +104,22 @@ class Hero{
} }
updateCharacterControls(delta) { updateCharacterControls(delta) {
let pc = this.pointerControls;
if (pc.controls.isLocked && this.model.visible){
this.model.visible = false;
this.camera.rotation.reorder('YXZ');
}
if (!pc.controls.isLocked && !this.model.visible){
this.model.visible = true;
this.#cameraZ = 5/1.77
this.camera.fov = 45;
this.camera.updateProjectionMatrix();
}
let input = this.getInput() let input = this.getInput()
let play = this.currentAction || 'idle', velocity = this.walkVelocity; let play = this.currentAction || 'idle', velocity = this.walkVelocity;
this.fadeDuration = 0.2; this.fadeDuration = 0.2;
if (input[1] && this.pointerControls.running) { if (input[1] && pc.running) {
play = 'run'; play = 'run';
velocity = this.runVelocity velocity = this.runVelocity
} else if (input[1] > 0) { } else if (input[1] > 0) {
@@ -152,23 +167,33 @@ class Hero{
} }
this.actionStart += delta; this.actionStart += delta;
this.cameraDelta += delta * ( this.pointerControls.cameraLeft * -1 + this.pointerControls.cameraRight * 1) this.cameraDelta += delta * ( pc.cameraLeft * -1 + pc.cameraRight * 1)
this.walkDirection.x = this.walkDirection.y = this.walkDirection.z = 0 this.walkDirection.setScalar(0);
if (this.pointerControls.kb.KeyR && this.cameraY < 5){ if (pc.kb.KeyR && this.cameraY < 5){
this.cameraY+=delta; this.cameraY+=delta;
} }
if (this.pointerControls.kb.KeyF && this.cameraY > 1){ if (pc.kb.KeyF && this.cameraY > 1){
this.cameraY-=delta; this.cameraY-=delta;
} }
if (this.pointerControls.motion) { if (pc.motion){
this.directionVelocity = this.directionVelocity * 2.5 * Math.abs(input[0]) if (!pc.controls.isLocked){
this.direction += input[0] * delta * 2.5 //this.directionVelocity; //this.directionVelocity = this.directionVelocity * 2.5 * Math.abs(input[0])
this.model.rotation.y = this.direction; this.direction += input[0] * delta * 2.5 //this.directionVelocity;
this.walkDirection.set(0, 0, input[1]) this.walkDirection.set(0, 0, input[1])
this.walkDirection.applyAxisAngle(this.rotateAngle, this.direction) this.walkDirection.applyAxisAngle(this.rotateAngle, this.direction)
}else{
this.direction = this.camera.rotation.y + Math.PI;
this.walkDirection.set(input[0], 0, input[1])
this.walkDirection.applyAxisAngle(this.rotateAngle, this.direction)
//console.log(this.camera.rotation.y * 180/Math.PI);
// this.camera.getWorldDirection(this.walkDirection);
// this.walkDirection.applyAxisAngle(this.rotateAngle, input[0]*Math.PI/2 + (input[1]<0 ? Math.PI : 0))
//this.walkDirection.multiplyScalar(input[1]);
}
this.walkDirection.normalize(); this.walkDirection.normalize();
this.model.rotation.y = this.direction;
} }
this.walkDirection.x = this.walkDirection.x * velocity * delta// + this.model.position.x this.walkDirection.x = this.walkDirection.x * velocity * delta// + this.model.position.x
@@ -203,18 +228,20 @@ class Hero{
let cameraPosition = new Vector3().copy(this.camera.position) let cameraPosition = new Vector3().copy(this.camera.position)
let cameraDesiredPosition = new Vector3( let cameraDesiredPosition = new Vector3(
this.model.position.x + this.#cameraZ* Math.sin(this.model.rotation.y + Math.PI + this.cameraDelta + this.cameraIdleDelta), this.model.position.x + this.#cameraZ* Math.sin(this.model.rotation.y + Math.PI + this.cameraDelta + this.cameraIdleDelta),
this.cameraY + this.model.position.y, pc.controls.isLocked? this.size.y*0.9 : (this.cameraY + this.model.position.y),
this.model.position.z + this.#cameraZ* Math.cos(this.model.rotation.y + Math.PI + this.cameraDelta + this.cameraIdleDelta) this.model.position.z + this.#cameraZ* Math.cos(this.model.rotation.y + Math.PI + this.cameraDelta + this.cameraIdleDelta)
) )
cameraPosition.lerp(cameraDesiredPosition, delta*2) cameraPosition.lerp(cameraDesiredPosition, delta*2)
this.camera.position.copy(cameraPosition) this.camera.position.copy(cameraPosition)
this.orbitControl.target.set( if (!pc.controls.isLocked){
this.model.position.x, this.orbitControl.target.set(
this.cameraY -this.size.y * 0.5 + this.model.position.y, this.model.position.x,
this.model.position.z this.cameraY -this.size.y * 0.5 + this.model.position.y,
) this.model.position.z
this.camera.lookAt(this.orbitControl.target) )
this.camera.lookAt(this.orbitControl.target)
}
} }
getInput() { getInput() {
-1
View File
@@ -1,5 +1,4 @@
import { Vector3 } from 'three'; import { Vector3 } from 'three';
import { PointerLockControls } from 'three/examples/jsm/Addons.js'; import { PointerLockControls } from 'three/examples/jsm/Addons.js';
class PointerControls { class PointerControls {