physics
This commit is contained in:
+183
@@ -0,0 +1,183 @@
|
||||
import { AnimationMixer } from 'three';
|
||||
import { PointerControls } from './PointerControls';
|
||||
import * as THREE from 'three';
|
||||
import * as CANNON from 'cannon-es';
|
||||
|
||||
class Hero{
|
||||
|
||||
constructor(object, data){
|
||||
this.object = object;
|
||||
this.data = data;
|
||||
this.model = object.scene
|
||||
}
|
||||
|
||||
init(gameEngine){
|
||||
this.gameEngine = gameEngine;
|
||||
this.mixer = new AnimationMixer(this.model);
|
||||
gameEngine.mixers.push( this.mixer );
|
||||
this.actionWalk = this.mixer.clipAction( this.object.animations.find(a=>a.name=='walk') );
|
||||
this.actionIdle = this.mixer.clipAction( this.object.animations.find(a=>a.name=='idle') );
|
||||
this.actionIdle.play();
|
||||
this.activeAction = this.actionIdle;
|
||||
this.pointerControls = new PointerControls(gameEngine.cameraPivot, this.model, gameEngine.renderer.domElement);
|
||||
gameEngine.hero = this;
|
||||
|
||||
// Character Collider
|
||||
const characterCollider = new THREE.Object3D()
|
||||
characterCollider.position.y = 3
|
||||
gameEngine.activeObjects.add(characterCollider)
|
||||
const colliderShape = new CANNON.Sphere(0.5)
|
||||
const colliderBody = new CANNON.Body({ mass: 1, material: gameEngine.phy.slipperyMaterial })
|
||||
colliderBody.addShape(colliderShape, new CANNON.Vec3(0, 0.5, 0))
|
||||
colliderBody.addShape(colliderShape, new CANNON.Vec3(0, -0.5, 0))
|
||||
colliderBody.position.set(
|
||||
characterCollider.position.x,
|
||||
characterCollider.position.y,
|
||||
characterCollider.position.z
|
||||
)
|
||||
colliderBody.linearDamping = 0.95
|
||||
colliderBody.angularFactor.set(0, 1, 0) // prevents rotation X,Z axis
|
||||
gameEngine.phy.world.addBody(colliderBody)
|
||||
|
||||
this.characterCollider = characterCollider;
|
||||
this.colliderBody = colliderBody;
|
||||
|
||||
this.clock = new THREE.Clock()
|
||||
this.delta = 0
|
||||
this.inputVelocity = new THREE.Vector3()
|
||||
this.velocity = new CANNON.Vec3()
|
||||
this.euler = new THREE.Euler()
|
||||
this.quat = new THREE.Quaternion()
|
||||
this.v = new THREE.Vector3()
|
||||
this.targetQuaternion = new THREE.Quaternion()
|
||||
this.distance = 0
|
||||
this.canJump = true;
|
||||
|
||||
this.contactNormal = new CANNON.Vec3()
|
||||
this.upAxis = new CANNON.Vec3(0, 1, 0)
|
||||
|
||||
colliderBody.addEventListener('collide', function (e) {
|
||||
const contact = e.contact
|
||||
if (contact.bi.id == this.colliderBody.id) {
|
||||
contact.ni.negate(this.contactNormal)
|
||||
} else {
|
||||
this.contactNormal.copy(contact.ni)
|
||||
}
|
||||
if (this.contactNormal.dot(this.upAxis) > 0.5) {
|
||||
if (!this.canJump) {
|
||||
setAction(animationActions[1], true)
|
||||
}
|
||||
this.canJump = true
|
||||
}
|
||||
}.bind(this))
|
||||
|
||||
|
||||
this.ready = true;
|
||||
}
|
||||
|
||||
lockControls(){
|
||||
this.pointerControls.controls.lock();
|
||||
}
|
||||
|
||||
setAction(toAction, loop){
|
||||
if (toAction != this.activeAction) {
|
||||
let lastAction = this.activeAction;
|
||||
this.activeAction = toAction
|
||||
lastAction.fadeOut(0.1)
|
||||
this.activeAction.reset()
|
||||
this.activeAction.fadeIn(0.1)
|
||||
this.activeAction.play()
|
||||
if (!loop) {
|
||||
this.activeAction.clampWhenFinished = true
|
||||
this.activeAction.loop = THREE.LoopOnce
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update(){
|
||||
let { inputVelocity, velocity, euler, quat, v, targetQuaternion, clock } = this;
|
||||
let pc = this.pointerControls;
|
||||
pc.update();
|
||||
if (this.ready) {
|
||||
if (this.canJump) {
|
||||
//walking
|
||||
this.mixer.update(this.distance / 100)
|
||||
} else {
|
||||
//were in the air
|
||||
this.mixer.update(this.delta)
|
||||
}
|
||||
const p = this.characterCollider.position
|
||||
p.y -= 1
|
||||
this.model.position.y = this.characterCollider.position.y
|
||||
this.distance = this.model.position.distanceTo(p)
|
||||
|
||||
const rotationMatrix = new THREE.Matrix4()
|
||||
rotationMatrix.lookAt(p, this.model.position, this.model.up)
|
||||
targetQuaternion.setFromRotationMatrix(rotationMatrix)
|
||||
|
||||
if (!this.model.quaternion.equals(targetQuaternion)) {
|
||||
this.model.quaternion.rotateTowards(targetQuaternion, this.delta * 10)
|
||||
}
|
||||
|
||||
if (this.canJump) {
|
||||
inputVelocity.set(0, 0, 0)
|
||||
|
||||
if (pc.moveForward) {
|
||||
inputVelocity.z = -1
|
||||
}
|
||||
if (pc.moveBackward) {
|
||||
inputVelocity.z = 1
|
||||
}
|
||||
|
||||
if (pc.moveLeft) {
|
||||
inputVelocity.x = -1
|
||||
}
|
||||
if (pc.moveRight) {
|
||||
inputVelocity.x = 1
|
||||
}
|
||||
|
||||
inputVelocity.setLength(this.delta * 100)
|
||||
|
||||
// apply camera rotation to inputVelocity
|
||||
euler.y = this.gameEngine.cameraYaw.rotation.y;
|
||||
//euler.y = this.gameEngine.camera.rotation.y;
|
||||
euler.order = 'XYZ'
|
||||
quat.setFromEuler(euler)
|
||||
inputVelocity.applyQuaternion(quat)
|
||||
}
|
||||
|
||||
if(inputVelocity.x || inputVelocity.z){
|
||||
this.setAction(this.actionWalk, true)
|
||||
}else{
|
||||
this.setAction(this.actionIdle, true)
|
||||
}
|
||||
|
||||
this.model.position.lerp(this.characterCollider.position, 1)
|
||||
}
|
||||
velocity.set(inputVelocity.x, inputVelocity.y, inputVelocity.z)
|
||||
this.colliderBody.applyImpulse(velocity)
|
||||
|
||||
this.delta = Math.min(clock.getDelta(), 0.1)
|
||||
this.gameEngine.phy.world.step(this.delta)
|
||||
|
||||
//cannonDebugRenderer.update()
|
||||
|
||||
this.characterCollider.position.set(this.colliderBody.position.x, this.colliderBody.position.y, this.colliderBody.position.z)
|
||||
// boxes.forEach((b, i) => {
|
||||
// boxMeshes[i].position.set(b.position.x, b.position.y, b.position.z)
|
||||
// boxMeshes[i].quaternion.set(b.quaternion.x, b.quaternion.y, b.quaternion.z, b.quaternion.w)
|
||||
// })
|
||||
|
||||
this.characterCollider.getWorldPosition(v)
|
||||
this.gameEngine.cameraPivot.position.lerp(v, 0.1)
|
||||
|
||||
// if (this.gameEngine.camera.position.distanceTo(v) > 200){
|
||||
// this.gameEngine.camera.position.set(v.x+10, 3, v.z + 30);
|
||||
// }
|
||||
//this.gameEngine.camera.lookAt(v.x, 3, v.z);
|
||||
//this.gameEngine.camera.rotation.y = this.model.rotation.y;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Hero }
|
||||
Reference in New Issue
Block a user