finish events

This commit is contained in:
2025-10-29 13:34:54 +02:00
parent 93e03b4843
commit 127f71f345
8 changed files with 104 additions and 82 deletions
+11 -21
View File
@@ -1,6 +1,5 @@
import * as THREE from 'three'
export const CONTROLLER_BODY_RADIUS = 0.28;
import { QueryFilterFlags } from '@dimforge/rapier3d';
export class CharacterControls {
@@ -33,7 +32,7 @@ export class CharacterControls {
// // Automatically slide down on slopes smaller than 30 degrees.
// this.characterController.setMinSlopeSlideAngle(30 * Math.PI / 180);
// this.characterController.enableAutostep(0.5, 0.2, true);
// this.characterController.setApplyImpulsesToDynamicBodies(true);
this.characterController.setApplyImpulsesToDynamicBodies(true);
// this.characterController.setCharacterMass(50);
this.po = po;
this.pointerControls = pointerControls
@@ -47,20 +46,14 @@ export class CharacterControls {
this.actionStart = 0;
this.cameraDelta = 0;
this.cameraIdleDelta = 0;
//this.toggleRun = true
}
switchRunToggle() {
this.toggleRun = !this.toggleRun
}
update(world, delta, pointerControls) {
const directionPressed = pointerControls.moving
let input = this.getInput(pointerControls)
let play = this.currentAction || 'idle', velocity = this.walkVelocity;
this.fadeDuration = 0.2;
if (input[1] && this.toggleRun) {
if (input[1] && pointerControls.running) {
play = 'run';
velocity = this.runVelocity
} else if (input[1] > 0) {
@@ -111,23 +104,13 @@ export class CharacterControls {
this.walkDirection.x = this.walkDirection.y = this.walkDirection.z = 0
if (directionPressed) {
if (pointerControls.motion) {
this.directionVelocity = this.directionVelocity * 2.5 * Math.abs(input[0])
this.direction += input[0] * delta * 2.5 //this.directionVelocity;
this.model.rotation.y = this.direction;
this.walkDirection.set(0, 0, input[1])
this.walkDirection.applyAxisAngle(this.rotateAngle, this.direction)
this.walkDirection.normalize();
//let dst = Math.sqrt(Math.pow(cameraPosition.x - this.model.position.x, 2) + Math.pow(cameraPosition.z - this.model.position.z, 2));
//cameraPosition.y = 8 - dst;
//if (dst >0.52){
//}
//this.camera.zoom = dst
//this.camera.updateProjectionMatrix();
// run/walk velocity
}
this.walkDirection.x = this.walkDirection.x * velocity * delta// + this.model.position.x
@@ -138,8 +121,15 @@ export class CharacterControls {
this.characterController.computeColliderMovement(
this.po.collider, // The collider we would like to move.
this.walkDirection, // The movement we would like to apply if there wasnt any obstacle.
QueryFilterFlags['EXCLUDE_SENSORS']
);
// for (let i = 0; i < this.characterController.numComputedCollisions(); i++) {
// let collision = this.characterController.computedCollision(i);
// //console.log(collision)
// // Do something with that collision information.
// }
let correctedMovement = this.characterController.computedMovement();
let v = new THREE.Vector3();
+2 -32
View File
@@ -17,7 +17,7 @@ import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFa
import { Physics } from './Physics.js';
import { Clickable } from './Clickable.js';
class GameEngine {
class GameEngine extends THREE.EventDispatcher{
async init(domNode, opts = {}) {
this.w = domNode.clientWidth || 1200, this.h = domNode.clientHeight || 800;
this.aspect = this.w / this.h
@@ -251,37 +251,7 @@ class GameEngine {
}
async initPhysics() {
//const world = new CANNON.World()
//world.gravity.set(0, -9.82, 0)
// let gravity = { x: 0.0, y: -9.81, z: 0.0 };
// let world = new RAPIER.World(gravity);
// // Create Ground.
// let bodyDesc = RAPIER.RigidBodyDesc.fixed();
// let body = world.createRigidBody(bodyDesc);
// let colliderDesc = RAPIER.ColliderDesc.cuboid(100.0, 0.1, 100.0);
// world.createCollider(colliderDesc, body.handle);
// const groundMaterial = new CANNON.Material('groundMaterial')
// const slipperyMaterial = new CANNON.Material('slipperyMaterial')
// const slippery_ground_cm = new CANNON.ContactMaterial(
// groundMaterial,
// slipperyMaterial,
// {
// friction: 0,
// restitution: 0.3,
// contactEquationStiffness: 1e10,
// contactEquationRelaxation: 30,
// }
// )
// world.addContactMaterial(slippery_ground_cm)
// const planeShape = new CANNON.Plane()
// const planeBody = new CANNON.Body({ mass: 0, material: groundMaterial })
// planeBody.addShape(planeShape)
// planeBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2)
// world.addBody(planeBody)
this.phy = new Physics();
this.phy = new Physics(this);
await this.phy.init();
}
+8 -8
View File
@@ -2,7 +2,6 @@ import { AnimationMixer } from 'three';
import { PointerControls } from './PointerControls';
import { CharacterControls } from './CharacterControls';
import * as THREE from 'three';
import * as RAPIER from '@dimforge/rapier3d'
class Hero{
@@ -18,9 +17,9 @@ class Hero{
gameEngine.camera.position.set(0,17,-30)
gameEngine.camera.lookAt(new THREE.Vector3(this.model.position.x, 5, this.model.position.z))
this.heroCamera = new THREE.Object3D()
this.model.add(this.heroCamera)
this.heroCamera.applyMatrix4(gameEngine.camera.matrix)
// this.heroCamera = new THREE.Object3D()
// this.model.add(this.heroCamera)
// this.heroCamera.applyMatrix4(gameEngine.camera.matrix)
this.mixer = new AnimationMixer(this.model);
gameEngine.mixers.push( this.mixer );
@@ -35,6 +34,7 @@ class Hero{
let po = gameEngine.phy.add(this.model, 'kinematicPositionBased', false, undefined, 'capsule', { radius: 0.5, halfHeight: 1})
po.collider.setTranslationWrtParent({ x: 0, y: 2.0, z: 0 });
//po.collider.setActiveEvents(RAPIER.ActiveEvents.COLLISION_EVENTS);
this.characterControls = new CharacterControls(this.model, this.mixer,
this.animationsMap, gameEngine, 'idle', po, this.pointerControls)
@@ -53,16 +53,16 @@ class Hero{
//return
if (this.gameEngine.renderer.xr.isPresenting) return;
if (this.ready) {
if (this.ready && !this.disableInput) {
let pc = this.pointerControls;
pc.update();
let dlt = this.clock.getDelta();
this.delta += dlt;
if (this.delta > 0.00001){
this.gameEngine.phy.step()
//if (this.delta > 0.00001){
this.characterControls.update(this.gameEngine.phy.world, this.delta, pc)
this.gameEngine.phy.step()
this.delta = 0;
}
//}
}
+19 -12
View File
@@ -1,16 +1,7 @@
import * as RAPIER from '@dimforge/rapier3d'
// export type PhysicsObject = {
// mesh: THREE.Mesh
// collider: Rapier.Collider
// rigidBody: Rapier.RigidBody
// fn?: Function
// autoAnimate: boolean
// }
class Physics{
constructor(){
constructor(engine){
this.engine = engine
}
init = async ()=>{
@@ -25,6 +16,7 @@ class Physics{
world.createCollider(colliderDesc, body.handle);
this.world = world;
this.physicsObjects = [];
this.eventQueue = new RAPIER.EventQueue(true);
return this;
}
@@ -34,6 +26,7 @@ class Physics{
// * Responsible for collision response
const rigidBody = this.world.createRigidBody(rigidBodyDesc)
rigidBody.userData = colliderSettings.userData || {};
let colliderDesc
@@ -73,6 +66,12 @@ class Physics{
console.error('Collider Mesh Error: convex mesh creation failed.')
}
if (colliderSettings.isSensor){
colliderDesc.setSensor(true);
colliderDesc.setActiveEvents(RAPIER.ActiveEvents.COLLISION_EVENTS);
colliderDesc.setActiveCollisionTypes(RAPIER.ActiveCollisionTypes.KINEMATIC_FIXED);
}
// * Responsible for collision detection
const collider = this.world.createCollider(colliderDesc, rigidBody)
@@ -84,7 +83,7 @@ class Physics{
}
step(){
this.world.step()
this.world.step(this.eventQueue)
for (let po of this.physicsObjects) {
const autoAnimate = po.autoAnimate
@@ -99,6 +98,14 @@ class Physics{
const fn = po.fn
fn && fn()
}
this.eventQueue.drainCollisionEvents((handle1, handle2, started) => {
/* Handle the collision event. */
//console.log(this.world.getCollider(handle2), handle1, started)
this.engine.dispatchEvent({
type: 'collision', handle1, handle2, started
})
});
}
}
+13 -1
View File
@@ -139,7 +139,19 @@ class PointerControls {
}
get moving(){
return this.moveForward || this.moveBackward || this.moveLeft || this.moveRight;
return this.moveForward || this.moveBackward;
}
get rotating(){
return this.rotateLeft || this.rotateRight;
}
get motion(){
return this.moving || this.rotating;
}
get running(){
return this.moving && this.kb.ShiftLeft;
}
}
+12
View File
@@ -58,5 +58,17 @@ export default {
shuffleArray(arr){
return arr.map(value => ({ value, sort: Math.random() }))
.sort((a, b) => a.sort - b.sort).map(({ value }) => value)
},
async wait(ms){
await new Promise((resolve, reject)=>{
setTimeout(resolve, ms)
})
},
async waitFor(expFn){
while (!expFn()){
await JsUtils.wait(200);
}
}
}