From 55a0a3de6550f0142b79ab40645c20b465ddded8 Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Mon, 10 Feb 2025 01:29:10 -0500 Subject: first person controls --- src/components/chatbubble.jsx | 42 ++++++++++++++++++----- src/components/ground.jsx | 17 ++++++++++ src/components/notes.jsx | 14 ++++++++ src/components/player.jsx | 78 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 src/components/ground.jsx create mode 100644 src/components/notes.jsx create mode 100644 src/components/player.jsx (limited to 'src/components') diff --git a/src/components/chatbubble.jsx b/src/components/chatbubble.jsx index b3f4ad5..a1ef114 100644 --- a/src/components/chatbubble.jsx +++ b/src/components/chatbubble.jsx @@ -1,25 +1,51 @@ -import { useRef, useState } from 'react' +import { useContext, useRef, useState } from 'react' import * as everforest from '../_everforest.module.scss' import { useGLTF } from '@react-three/drei'; -import { useFrame } from '@react-three/fiber'; +import { useFrame, useThree } from '@react-three/fiber'; +import { Html } from '@react-three/drei'; +import { AppContext } from '../App'; +import Color from 'color'; +import { Vector3 } from 'three'; -export default function ChatBubble(props) { +export default function ChatBubble({ position, text }) { const meshRef = useRef(); const [hovered, setHovered] = useState(false); + const [activatable, setActivatable] = useState(false); const [active, setActive] = useState(false); - useFrame((_, delta) => (meshRef.current.rotation.y += delta)); - const {nodes} = useGLTF('../assets/message-bubble.glb'); + const { keysPressed } = useContext(AppContext); + const { camera } = useThree(); + useFrame((_, delta) => { + if (active) { + meshRef.current.rotation.y += delta; + } + if(hovered) { + let cameraPos = new Vector3(); + camera.getWorldPosition(cameraPos); + setActivatable(cameraPos.distanceToSquared(meshRef.current.position) < 9); + } else { + setActivatable(false); + } + if (keysPressed.includes('KeyE') && activatable) { + setActive(!active); + } + }); + const { nodes } = useGLTF('../assets/message-bubble.glb'); + let color = Color(active ? everforest.blue : everforest.orange); + if (activatable) { + color = color.lighten(.1); + } return ( setActive(!active)} geometry={nodes.Curve.geometry} + castShadow onPointerOver={(_) => setHovered(true)} onPointerOut={(_) => setHovered(false)}> - + + {active && {text}} ) } diff --git a/src/components/ground.jsx b/src/components/ground.jsx new file mode 100644 index 0000000..4042538 --- /dev/null +++ b/src/components/ground.jsx @@ -0,0 +1,17 @@ +import { useRef } from 'react'; +import * as everforest from '../_everforest.module.scss' +import { RigidBody } from '@react-three/rapier'; +import { DoubleSide } from 'three'; +import { useGLTF } from '@react-three/drei'; + +export default function Ground() { + const meshRef = useRef(); + const { nodes } = useGLTF('../assets/terrain.glb'); + return ( + + + + + + ); +} diff --git a/src/components/notes.jsx b/src/components/notes.jsx new file mode 100644 index 0000000..0dd267a --- /dev/null +++ b/src/components/notes.jsx @@ -0,0 +1,14 @@ +import ChatBubble from "./chatbubble"; + +const chatbubbles = [ + {position: [0,0,-3], text: "ugh. really struggling with double bleeds in my ankles. makes it hard to do very much of anything, let alone focus for my hobbies"}, + {position: [-1,0,-5], text: "reddit is everywhere on google and i am sick of it... why can't there be a good forum site?"}, +]; + +export default function Notes() { + return (<> + {chatbubbles.map((chatbubble, index) => + + )} + ); +} 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 ( + + + + + + ); +} + -- cgit v1.2.3