player controls moved to CharacterView
This commit is contained in:
parent
9aacd70abc
commit
8daa62ad8e
|
|
@ -2,12 +2,54 @@ import { observer } from "mobx-react-lite";
|
||||||
import type { Character } from "../types";
|
import type { Character } from "../types";
|
||||||
import { SyncRigidBody } from "./SyncRigidBody";
|
import { SyncRigidBody } from "./SyncRigidBody";
|
||||||
import { state } from "../state";
|
import { state } from "../state";
|
||||||
|
import { useRef } from "react";
|
||||||
|
import { Vector3 } from "three";
|
||||||
|
import { useFrame } from "@react-three/fiber";
|
||||||
|
import { PointerLockControls, useKeyboardControls } from "@react-three/drei";
|
||||||
|
import type { RapierRigidBody } from "@react-three/rapier";
|
||||||
|
|
||||||
export const CharacterView = observer(function ({ character }: { character: Character }) {
|
const SPEED = 5;
|
||||||
|
const _fwd = new Vector3();
|
||||||
|
|
||||||
|
type CharacterViewProps = {
|
||||||
|
character: Character;
|
||||||
|
editMode?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CharacterView = observer(function ({ character, editMode }: CharacterViewProps) {
|
||||||
const pos = character.transform.position;
|
const pos = character.transform.position;
|
||||||
|
|
||||||
return (
|
const rbRef = useRef<RapierRigidBody>(null);
|
||||||
|
|
||||||
|
const [, get] = useKeyboardControls();
|
||||||
|
|
||||||
|
useFrame(({ camera }) => {
|
||||||
|
if (state.game?.isPaused || !rbRef.current)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!editMode) {
|
||||||
|
const { forward, backward, left, right } = get();
|
||||||
|
|
||||||
|
camera.getWorldDirection(_fwd);
|
||||||
|
_fwd.y = 0;
|
||||||
|
_fwd.normalize();
|
||||||
|
const fx = _fwd.x, fz = _fwd.z;
|
||||||
|
|
||||||
|
const fwdScale = (forward ? 1 : 0) - (backward ? 1 : 0);
|
||||||
|
const rightScale = (right ? 1 : 0) - (left ? 1 : 0);
|
||||||
|
|
||||||
|
const vx = (fx * fwdScale - fz * rightScale) * SPEED;
|
||||||
|
const vz = (fz * fwdScale + fx * rightScale) * SPEED;
|
||||||
|
|
||||||
|
const cur = rbRef.current.linvel();
|
||||||
|
rbRef.current.setLinvel({ x: vx, y: cur.y, z: vz }, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
{!editMode && <PointerLockControls />}
|
||||||
<SyncRigidBody
|
<SyncRigidBody
|
||||||
|
ref={rbRef}
|
||||||
colliders="cuboid"
|
colliders="cuboid"
|
||||||
position={[pos[0] + 0.5, pos[1] + 0.5, pos[2] + 0.5]}
|
position={[pos[0] + 0.5, pos[1] + 0.5, pos[2] + 0.5]}
|
||||||
rotation={character.transform.look}
|
rotation={character.transform.look}
|
||||||
|
|
@ -18,17 +60,16 @@ export const CharacterView = observer(function ({ character }: { character: Char
|
||||||
look: character.transform.look,
|
look: character.transform.look,
|
||||||
},
|
},
|
||||||
data.linearVelocity,
|
data.linearVelocity,
|
||||||
undefined, // do not change radial velocity
|
undefined,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<group>
|
<group>
|
||||||
<mesh position={[0, 0, 0]} rotation={[-Math.PI / 2, -Math.PI / 4, 0]}>
|
<mesh rotation={[-Math.PI / 2, -Math.PI / 4, 0]}>
|
||||||
<coneGeometry args={[0.55, 0.8, 4]} />
|
<coneGeometry args={[0.55, 0.8, 4]} />
|
||||||
<meshStandardMaterial color="yellow" />
|
<meshStandardMaterial color="yellow" />
|
||||||
</mesh>
|
</mesh>
|
||||||
{/* <ConvexHullCollider args={[object.cache.colliderMesh[0]]} /> */}
|
|
||||||
</group>
|
</group>
|
||||||
</SyncRigidBody>
|
</SyncRigidBody>
|
||||||
);
|
</>);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,41 +2,9 @@ import { observer } from "mobx-react-lite";
|
||||||
import { SceneView } from "./SceneView";
|
import { SceneView } from "./SceneView";
|
||||||
import { state } from "../state";
|
import { state } from "../state";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { PointerLockControls, useKeyboardControls } from "@react-three/drei";
|
import { Suspense } from "react";
|
||||||
import { Suspense, useRef } from "react";
|
|
||||||
import { Physics } from "@react-three/rapier";
|
import { Physics } from "@react-three/rapier";
|
||||||
|
|
||||||
function PlayerMovement() {
|
|
||||||
const [, get] = useKeyboardControls();
|
|
||||||
const dirty = useRef(false);
|
|
||||||
|
|
||||||
useFrame(({ camera }, dt) => {
|
|
||||||
if (state.game?.isPaused)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const { forward, backward, left, right } = get();
|
|
||||||
const speed = 5 * dt;
|
|
||||||
if (forward) { camera.translateZ(-speed); dirty.current = true; }
|
|
||||||
if (backward) { camera.translateZ(speed); dirty.current = true; }
|
|
||||||
if (left) { camera.translateX(-speed); dirty.current = true; }
|
|
||||||
if (right) { camera.translateX(speed); dirty.current = true; }
|
|
||||||
|
|
||||||
if (!dirty.current) return;
|
|
||||||
dirty.current = false;
|
|
||||||
|
|
||||||
const [rx, ry, rz] = camera.rotation.toArray();
|
|
||||||
state.game?.setCharacterTransform(
|
|
||||||
{
|
|
||||||
position: camera.position.toArray(),
|
|
||||||
look: [rx, ry, rz],
|
|
||||||
},
|
|
||||||
// do not change velocities
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return <PointerLockControls onChange={() => { dirty.current = true; }} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GameView = observer(function () {
|
export const GameView = observer(function () {
|
||||||
const game = state.game;
|
const game = state.game;
|
||||||
const { camera } = useThree();
|
const { camera } = useThree();
|
||||||
|
|
@ -44,7 +12,8 @@ export const GameView = observer(function () {
|
||||||
useFrame((_, delta) => {
|
useFrame((_, delta) => {
|
||||||
state.game?.tick(delta);
|
state.game?.tick(delta);
|
||||||
|
|
||||||
if (!game) return;
|
if (!game)
|
||||||
|
return;
|
||||||
const { position, look } = game.camera;
|
const { position, look } = game.camera;
|
||||||
camera.position.set(position[0], position[1], position[2]);
|
camera.position.set(position[0], position[1], position[2]);
|
||||||
camera.rotation.set(look[0], look[1], look[2]);
|
camera.rotation.set(look[0], look[1], look[2]);
|
||||||
|
|
@ -55,7 +24,6 @@ export const GameView = observer(function () {
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<PlayerMovement />
|
|
||||||
<Physics paused={game.isPaused} debug>
|
<Physics paused={game.isPaused} debug>
|
||||||
<SceneView scene={game.scene} />
|
<SceneView scene={game.scene} />
|
||||||
</Physics>
|
</Physics>
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,14 @@ export const SceneView = observer(function (props: SceneViewProps) {
|
||||||
// const rapier = useRapier();
|
// const rapier = useRapier();
|
||||||
|
|
||||||
// useFrame((_, dt) => {
|
// useFrame((_, dt) => {
|
||||||
// if (props.editMode)
|
// if (props.editMode)
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
// const game = state.game;
|
// const game = state.game;
|
||||||
// if (!game || game.isPaused)
|
// if (!game || game.isPaused)
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
// rapier.step(dt);
|
// rapier.step(dt);
|
||||||
// })
|
// })
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
|
|
@ -34,6 +34,6 @@ export const SceneView = observer(function (props: SceneViewProps) {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
{/* {props.editMode && <CharacterView character={props.scene.character} />} */}
|
{/* {props.editMode && <CharacterView character={props.scene.character} />} */}
|
||||||
{<CharacterView character={props.scene.character} />}
|
{<CharacterView character={props.scene.character} editMode={props.editMode} />}
|
||||||
</>);
|
</>);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { RigidBody, type RigidBodyProps, type RapierRigidBody } from "@react-three/rapier";
|
import { RigidBody, type RigidBodyProps, type RapierRigidBody } from "@react-three/rapier";
|
||||||
import { useFrame } from "@react-three/fiber";
|
import { useFrame } from "@react-three/fiber";
|
||||||
import { useRef } from "react";
|
import { useImperativeHandle, useRef, type Ref } from "react";
|
||||||
import { Euler, Quaternion } from "three";
|
import { Euler, Quaternion } from "three";
|
||||||
import type { R3, V3 } from "../types";
|
import type { R3, V3 } from "../types";
|
||||||
|
|
||||||
|
|
@ -15,6 +15,7 @@ export type SyncRigidBodyOnSyncFunction = (data: SyncRigidBodyData) => void;
|
||||||
|
|
||||||
type SyncRigidBodyProps = RigidBodyProps & {
|
type SyncRigidBodyProps = RigidBodyProps & {
|
||||||
onSync: SyncRigidBodyOnSyncFunction;
|
onSync: SyncRigidBodyOnSyncFunction;
|
||||||
|
ref?: Ref<RapierRigidBody | null>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const _q = new Quaternion();
|
const _q = new Quaternion();
|
||||||
|
|
@ -38,8 +39,11 @@ function compareTwoFloatArrays(a: Float64Array, b: Float64Array, epsilon: number
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SyncRigidBody({ onSync, children, ...props }: SyncRigidBodyProps) {
|
export function SyncRigidBody({ onSync, ref, children, ...props }: SyncRigidBodyProps) {
|
||||||
const rbRef = useRef<RapierRigidBody>(null);
|
const rbRef = useRef<RapierRigidBody>(null);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => rbRef.current!);
|
||||||
|
|
||||||
const prevData = useRef<Float64Array>(PREV_INIT.slice());
|
const prevData = useRef<Float64Array>(PREV_INIT.slice());
|
||||||
const currentData = useRef<Float64Array>(PREV_INIT.slice());
|
const currentData = useRef<Float64Array>(PREV_INIT.slice());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue