Add animation triggers code

master
Ian Mancini 4 years ago
parent b6aa28f220
commit 94bc4d114b

@ -23,7 +23,7 @@ const Phantom: React.FC<PhantomProps> = ({ id }) => {
state.position[1] + 0.25,
state.position[2],
])
ref.current?.rotation.fromArray(state.rotation)
ref.current?.quaternion.fromArray(state.rotation)
},
(state) => state?.userTransforms?.[id],
)

@ -10,10 +10,12 @@ import {
Mesh,
CircleGeometry,
} from 'three'
import { relativeAngle } from './lib/math'
import WorldCollisions from './models/WorldCollisions'
import useStore from '../store'
import { MeshBasicMaterial } from 'three/src/materials/MeshBasicMaterial'
import { Quaternion } from 'three/src/math/Quaternion'
const SPEED = 1
const HEIGHT = 1.5
@ -22,10 +24,10 @@ const CIRCLE_SEGMENTS = 8
const InitialPosition = new Vector3(49.92, 3.15, 34.52)
const keys: Record<string, string> = {
KeyW: 'forward',
KeyS: 'backward',
KeyA: 'left',
KeyD: 'right',
KeyW: 'left',
KeyS: 'right',
KeyA: 'backward',
KeyD: 'forward',
ArrowUp: 'forward',
ArrowDown: 'backward',
ArrowLeft: 'left',
@ -35,6 +37,20 @@ const keys: Record<string, string> = {
}
const moveFieldByKey = (key: string) => keys[key]
const animations: Record<string, number> = {
idle: 0,
turn_right: 1,
turn_left: 2,
walk_backwards: 3,
walk: 4,
walk_right: 5,
walk_left: 6,
run: 7,
run_right: 8,
run_left: 9,
jump: 10,
}
function FirstPersonCamera(props: JSX.IntrinsicElements['perspectiveCamera']) {
const ref = useRef<PerspectiveCamera>()
const { setDefaultCamera } = useThree()
@ -73,6 +89,9 @@ const usePlayerControls = () => {
return movement
}
// define an axis, usually just up
const upVector = new Vector3(0, 1, 0)
// TODO Improve physics in player
const Player = () => {
const socket = useStore((state) => state.socket)
@ -84,8 +103,10 @@ const Player = () => {
const collisionsRef = useRef<Mesh<CircleGeometry, MeshBasicMaterial>>(null)
const velocity = useRef<Vector3>(new Vector3())
const direction = useRef<Vector3>(new Vector3())
const worldOrigin = useRef<Vector3>(new Vector3())
const currentPositionClone = useRef<Vector3>(new Vector3())
const pCameraQuaternion = useRef<Quaternion>(new Quaternion())
const worldOrigin = useRef<Vector3>(new Vector3())
const speed = useRef<number>(SPEED)
const bottomRaycaster = useRef(
new Raycaster(new Vector3(), new Vector3(0, -1, 0), 0, HEIGHT + 0.5),
@ -113,22 +134,53 @@ const Player = () => {
useEffect(() => {
const socketEmitTransformInterval = setInterval(() => {
if (socket && groupRef.current && camera) {
const cameraRotation = camera.rotation.toArray()
const cameraRotation = camera.quaternion.toArray()
const [x, , z] = direction.current.toArray()
let anim = animations.idle
if (x === 0 && z === 0) {
const rotationAngle = relativeAngle(
upVector,
camera.quaternion,
pCameraQuaternion.current,
)
if (Math.abs(rotationAngle) > 10) {
anim =
rotationAngle > 1 ? animations.turn_right : (anim = animations.turn_left)
} else {
anim = animations.idle
}
} else if (x < 0) {
anim = animations.walk_backwards
} else if (x > 0 && z === 0) {
anim = speed.current > SPEED ? animations.run : animations.walk
} else if (x >= 0 && z > 0) {
anim = speed.current > SPEED ? animations.run_right : animations.walk_right
} else if (x >= 0 && z < 0) {
anim = speed.current > SPEED ? animations.run_left : animations.walk_left
}
// get the signed difference in these angles
socket.emit('transform', {
position: [
groupRef.current?.position.x,
groupRef.current?.position.y,
groupRef.current?.position.z,
],
rotation: [cameraRotation[0], cameraRotation[1], cameraRotation[2]],
rotation: [...cameraRotation],
a: anim,
})
pCameraQuaternion.current.copy(camera.quaternion)
}
}, 50)
}, 1000)
return () => {
clearInterval(socketEmitTransformInterval)
}
}, [])
}, [socket, groupRef.current, camera])
const moveForward = (distance: number) => {
if (groupRef.current) {
@ -175,12 +227,13 @@ const Player = () => {
direction.current.normalize()
// Running
const speed = run ? 1.5 : 1
speed.current = run && direction.current.x >= 0 ? 1.5 : 1
// Move
if (forward || backward)
velocity.current.z -= direction.current.z * SPEED * delta * speed
if (left || right) velocity.current.x -= direction.current.x * SPEED * delta * speed
velocity.current.z -= direction.current.z * SPEED * delta * speed.current
if (left || right)
velocity.current.x -= direction.current.x * SPEED * delta * speed.current
// Wall collisions
const collisionCircleGeometry = collisionCircle.current.geometry as Geometry
@ -213,8 +266,8 @@ const Player = () => {
}
// Apply speed
moveForward(-velocity.current.x * speed)
moveRight(-velocity.current.z * speed)
moveForward(-velocity.current.x * speed.current)
moveRight(-velocity.current.z * speed.current)
groupRef.current.position.y += velocity.current.y * delta
}
@ -224,8 +277,8 @@ const Player = () => {
})
return (
<>
<group ref={groupRef} position={InitialPosition} rotation={[0, -Math.PI / 2, 0]}>
<FirstPersonCamera rotation={[0, Math.PI / 2, 0]} />
<group ref={groupRef} position={InitialPosition}>
<FirstPersonCamera />
<mesh
ref={collisionCircle}
position={[0, -HEIGHT / 2, 0]}

@ -0,0 +1,42 @@
import { MathUtils, Quaternion, Vector3 } from 'three'
export const multiplyQuaternionVector3 = (rotation: Quaternion, point: Vector3) => {
const num1 = rotation.x * 2
const num2 = rotation.y * 2
const num3 = rotation.z * 2
const num4 = rotation.x * num1
const num5 = rotation.y * num2
const num6 = rotation.z * num3
const num7 = rotation.x * num2
const num8 = rotation.x * num3
const num9 = rotation.y * num3
const num10 = rotation.w * num1
const num11 = rotation.w * num2
const num12 = rotation.w * num3
const v = new Vector3()
v.x =
(1.0 - (num5 + num6)) * point.x + (num7 - num12) * point.y + (num8 + num11) * point.z
v.y =
(num7 + num12) * point.x + (1.0 - (num4 + num6)) * point.y + (num9 - num10) * point.z
v.z =
(num8 - num11) * point.x + (num9 + num10) * point.y + (1.0 - (num4 + num5)) * point.z
return v
}
export const repeat = (t: number, length: number): number => {
return t - Math.floor(t / length) * length
}
export const deltaAngle = (current: number, target: number): number => {
let num = repeat(target - current, 360)
if (num > 180) num -= 360
return num
}
export const relativeAngle = (axis: Vector3, q1: Quaternion, q2: Quaternion): number => {
const vecA = multiplyQuaternionVector3(q1, axis)
const vecB = multiplyQuaternionVector3(q2, axis)
const angleA = MathUtils.radToDeg(Math.atan2(vecA.x, vecA.z))
const angleB = MathUtils.radToDeg(Math.atan2(vecB.x, vecB.z))
return deltaAngle(angleA, angleB)
}
Loading…
Cancel
Save