r3f-starter
Version:
CLI to scaffold React Three Fiber templates with or without physics( Rapier )
68 lines (57 loc) • 1.87 kB
JSX
import { useKeyboardControls } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import { RigidBody } from "@react-three/rapier";
import { useRef } from "react";
import { Vector3 } from "three";
import { useThree } from "@react-three/fiber";
const Player = () => {
const body = useRef(null);
const direction = new Vector3();
const { camera } = useThree();
const [, get] = useKeyboardControls();
useFrame(() => {
const rb = body.current;
if (!rb) return;
const { forward, backward, left, right, jump } = get();
// Get forward/right directions based on camera rotation
const cameraDir = new Vector3();
camera.getWorldDirection(cameraDir);
cameraDir.y = 0;
cameraDir.normalize();
const cameraRight = new Vector3();
cameraRight.crossVectors(camera.up, cameraDir).normalize();
// Construct movement direction
direction.set(0, 0, 0);
if (forward) direction.add(cameraDir);
if (backward) direction.sub(cameraDir);
if (left) direction.add(cameraRight);
if (right) direction.sub(cameraRight);
direction.normalize().multiplyScalar(4);
const linvel = rb.linvel();
rb.setLinvel({ x: direction.x, y: linvel.y, z: direction.z }, true);
if (jump && Math.abs(linvel.y) < 0.05) {
rb.setLinvel({ x: linvel.x, y: 5, z: linvel.z }, true);
}
// Camera follows player
const pos = rb.translation();
camera.position.set(pos.x, pos.y + 1.5, pos.z);
});
return (
<RigidBody
ref={body}
type="dynamic"
position={[0, 2, 0]}
colliders="hull"
friction={1}
canSleep={false}
lockRotations
>
{/* dummy capsule mesh */}
<mesh>
<capsuleGeometry args={[0.5, 1, 8, 16]} />
<meshBasicMaterial transparent opacity={0} />
</mesh>
</RigidBody>
);
};
export default Player;