new physics engine - rapier instead of cannon
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
import * as THREE from 'three'
|
||||
|
||||
export const CONTROLLER_BODY_RADIUS = 0.28;
|
||||
|
||||
export class CharacterControls {
|
||||
|
||||
// temporary data
|
||||
walkDirection = new THREE.Vector3()
|
||||
rotateAngle = new THREE.Vector3(0, 1, 0)
|
||||
rotateQuarternion = new THREE.Quaternion()
|
||||
cameraTarget = new THREE.Vector3()
|
||||
storedFall = 0
|
||||
|
||||
// constants
|
||||
fadeDuration = 0.2
|
||||
runVelocity = 7
|
||||
walkVelocity = 3
|
||||
lerp = (x, y, a) => x * (1 - a) + y * a;
|
||||
|
||||
constructor(model, mixer, animationsMap, orbitControl, camera, currentAction, ray, rigidBody, pointerControls) {
|
||||
this.model = model
|
||||
this.mixer = mixer
|
||||
this.animationsMap = animationsMap
|
||||
this.currentAction = currentAction
|
||||
this.animationsMap[currentAction].play()
|
||||
|
||||
this.ray = ray
|
||||
this.rigidBody = rigidBody
|
||||
this.pointerControls = pointerControls
|
||||
|
||||
this.orbitControl = orbitControl
|
||||
this.camera = camera
|
||||
this.updateCameraTarget(new THREE.Vector3(0,1,5))
|
||||
}
|
||||
|
||||
switchRunToggle() {
|
||||
this.toggleRun = !this.toggleRun
|
||||
}
|
||||
|
||||
update(world, delta, pointerControls) {
|
||||
const directionPressed = pointerControls.moving()
|
||||
|
||||
var play = '';
|
||||
if (directionPressed && this.toggleRun) {
|
||||
play = 'run'
|
||||
} else if (directionPressed) {
|
||||
play = 'walk'
|
||||
} else {
|
||||
play = 'idle'
|
||||
}
|
||||
|
||||
if (this.currentAction != play) {
|
||||
const toPlay = this.animationsMap[play]
|
||||
const current = this.animationsMap[this.currentAction]
|
||||
|
||||
current.fadeOut(this.fadeDuration)
|
||||
toPlay.reset().fadeIn(this.fadeDuration).play();
|
||||
|
||||
this.currentAction = play
|
||||
}
|
||||
|
||||
this.mixer.update(delta)
|
||||
|
||||
this.walkDirection.x = this.walkDirection.y = this.walkDirection.z = 0
|
||||
|
||||
let velocity = 0
|
||||
if (this.currentAction == 'run' || this.currentAction == 'walk') {
|
||||
// calculate towards camera direction
|
||||
var angleYCameraDirection = Math.atan2(
|
||||
(this.camera.position.x - this.model.position.x),
|
||||
(this.camera.position.z - this.model.position.z))
|
||||
// diagonal movement angle offset
|
||||
var directionOffset = this.directionOffset(pointerControls)
|
||||
|
||||
// rotate model
|
||||
this.rotateQuarternion.setFromAxisAngle(this.rotateAngle, Math.PI + angleYCameraDirection + directionOffset)
|
||||
this.model.quaternion.rotateTowards(this.rotateQuarternion, 0.2)
|
||||
|
||||
// calculate direction
|
||||
this.camera.getWorldDirection(this.walkDirection)
|
||||
this.walkDirection.y = 0
|
||||
this.walkDirection.normalize()
|
||||
this.walkDirection.applyAxisAngle(this.rotateAngle, directionOffset)
|
||||
|
||||
// run/walk velocity
|
||||
velocity = this.currentAction == 'run' ? this.runVelocity : this.walkVelocity
|
||||
}
|
||||
|
||||
const translation = this.rigidBody.translation();
|
||||
if (translation.y < -1) {
|
||||
// don't fall below ground
|
||||
this.rigidBody.setNextKinematicTranslation( {
|
||||
x: 0,
|
||||
y: 10,
|
||||
z: 0
|
||||
});
|
||||
} else {
|
||||
const cameraPositionOffset = this.camera.position.sub(this.model.position);
|
||||
// update model and camera
|
||||
this.model.position.x = translation.x
|
||||
this.model.position.y = translation.y
|
||||
this.model.position.z = translation.z
|
||||
this.updateCameraTarget(cameraPositionOffset)
|
||||
|
||||
this.walkDirection.y += this.lerp(this.storedFall, -9.81 * delta, 0.10)
|
||||
this.storedFall = this.walkDirection.y
|
||||
this.ray.origin.x = translation.x
|
||||
this.ray.origin.y = translation.y
|
||||
this.ray.origin.z = translation.z
|
||||
let hit = world.castRay(this.ray, 0.5, false, 0xfffffffff);
|
||||
if (hit) {
|
||||
const point = this.ray.pointAt(hit.timeOfImpact);
|
||||
let diff = translation.y - ( point.y + CONTROLLER_BODY_RADIUS);
|
||||
if (diff < 0.0) {
|
||||
this.storedFall = 0
|
||||
this.walkDirection.y = this.lerp(0, -diff, 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
this.walkDirection.x = this.walkDirection.x * velocity * delta
|
||||
this.walkDirection.z = this.walkDirection.z * velocity * delta
|
||||
|
||||
this.rigidBody.setNextKinematicTranslation( {
|
||||
x: translation.x + this.walkDirection.x,
|
||||
y: translation.y + this.walkDirection.y,
|
||||
z: translation.z + this.walkDirection.z
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
updateCameraTarget(offset) {
|
||||
// move camera
|
||||
const rigidTranslation = this.rigidBody.translation();
|
||||
this.camera.position.x = rigidTranslation.x + offset.x
|
||||
this.camera.position.y = rigidTranslation.y + offset.y
|
||||
this.camera.position.z = rigidTranslation.z + offset.z
|
||||
|
||||
// update camera target
|
||||
this.cameraTarget.x = rigidTranslation.x
|
||||
this.cameraTarget.y = rigidTranslation.y + 1
|
||||
this.cameraTarget.z = rigidTranslation.z
|
||||
this.orbitControl.target = this.cameraTarget
|
||||
}
|
||||
|
||||
directionOffset(pointerControls) {
|
||||
var directionOffset = 0 // w
|
||||
|
||||
if (pointerControls.moveForward) {
|
||||
if (pointerControls.moveLeft) {
|
||||
directionOffset = Math.PI / 4 // w+a
|
||||
} else if (pointerControls.moveRight) {
|
||||
directionOffset = - Math.PI / 4 // w+d
|
||||
}
|
||||
} else if (pointerControls.moveBackward) {
|
||||
if (pointerControls.moveLeft) {
|
||||
directionOffset = Math.PI / 4 + Math.PI / 2 // s+a
|
||||
} else if (pointerControls.moveRight) {
|
||||
directionOffset = -Math.PI / 4 - Math.PI / 2 // s+d
|
||||
} else {
|
||||
directionOffset = Math.PI // s
|
||||
}
|
||||
} else if (pointerControls.moveLeft) {
|
||||
directionOffset = Math.PI / 2 // a
|
||||
} else if (pointerControls.moveRight) {
|
||||
directionOffset = - Math.PI / 2 // d
|
||||
}
|
||||
|
||||
return directionOffset
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user