diff options
Diffstat (limited to 'src/components/player.jsx')
-rw-r--r-- | src/components/player.jsx | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/components/player.jsx b/src/components/player.jsx new file mode 100644 index 0000000..bd8e392 --- /dev/null +++ b/src/components/player.jsx @@ -0,0 +1,78 @@ +import { Capsule, PerspectiveCamera, PointerLockControls } from "@react-three/drei"; +import { useFrame } from "@react-three/fiber"; +import { useContext, useEffect, useRef } from "react"; +import { AppContext } from "../App"; +import { CapsuleCollider, RapierCollider, RapierRigidBody, RigidBody, useRapier, vec3 } from "@react-three/rapier"; +import { quat } from "@react-three/rapier"; +import { Euler, Object3D, Vector3 } from "three"; +import { useBeforePhysicsStep } from "@react-three/rapier"; + +const _movespeed = 3.0; + +export default function Player() { + const controlsRef = useRef(); + const { keys } = useContext(AppContext); + const rapier = useRapier(); + const controller = useRef(); + const collider = useRef(); + const rigidbody = useRef(); + const camera = useRef(); + + const refState = useRef({ + grounded: false, + jumping: false, + velocity: vec3(), + }); + + useEffect(() => { + const c = rapier.world.createCharacterController(0.1); + c.setApplyImpulsesToDynamicBodies(true); + c.setCharacterMass(0.2); + controller.current = c; + }, [rapier]); + + useBeforePhysicsStep((world) => { + if (controller.current && rigidbody.current && collider.current) { + const move_axis_x = +(keys.includes('KeyD')) - +(keys.includes('KeyA')); + const move_axis_z = +(keys.includes('KeyW')) - +(keys.includes('KeyS')); + + const { velocity } = refState.current; + const position = vec3(rigidbody.current.translation()); + const movement = vec3(); + + const forward = new Vector3(); + camera.current.getWorldDirection(forward); + const left = new Vector3().crossVectors(forward, camera.current.up); + + movement.x += move_axis_z * world.timestep * _movespeed * forward.x; + movement.z += move_axis_z * world.timestep * _movespeed * forward.z; + movement.x += move_axis_x * world.timestep * _movespeed * left.x; + movement.z += move_axis_x * world.timestep * _movespeed * left.z; + + if (refState.current.grounded) { + velocity.y = 0; + } else { + velocity.y -= 9.81 * world.timestep * world.timestep; + } + + movement.add(velocity); + + controller.current.computeColliderMovement(collider.current, movement); + refState.current.grounded = controller.current.computedGrounded(); + + let correctedMovement = controller.current.computedMovement(); + position.add(vec3(correctedMovement)); + + rigidbody.current.setNextKinematicTranslation(position); + } + }); + + return ( + <RigidBody type="kinematicPosition" colliders={false} ref={rigidbody} position={[0, 2, 0]}> + <PerspectiveCamera makeDefault position={[0, .9, 0]} fov={90} ref={camera} /> + <PointerLockControls ref={controlsRef} /> + <CapsuleCollider ref={collider} args={[1, 0.5]} /> + </RigidBody> + ); +} + |