Open hichemfantar opened 1 week ago
Related to #29 too
This is a flying POC I created.
A stand-in replacement for <Ecctrl />
(replace with <EcctrlWithFlight />
)
Press "F" to toggle flying mode. Press "Space" to go up, Press "Shift" to go down. Arrows move on the x/z axis
import {KeyboardEvent, useEffect, useRef, useState } from "react";
import { useKeyboardControls } from "@react-three/drei";
import Ecctrl, { EcctrlProps } from "ecctrl";
import { useFrame } from "@react-three/fiber";
import { RapierRigidBody } from "@react-three/rapier";
const Flying: EcctrlProps = {
jumpVel: 2,
jumpForceToGroundMult: 0,
fallingMaxVel: 0,
fallingGravityScale: 0,
};
function useIsInsideKeyboardControls() {
try {
return !!useKeyboardControls();
} catch (e) {
return false;
}
}
export type EcctrlWithFlightProps = EcctrlProps & {
domElement?: HTMLElement;
};
export default function EcctrlWithFlight({ domElement, ...props }: EcctrlWithFlightProps) {
const cref = useRef<RapierRigidBody | undefined>();
const isInsideKeyboardControls = useIsInsideKeyboardControls();
const [, getKeys] = isInsideKeyboardControls ? useKeyboardControls() : [null];
const [flying, setFlying] = useState(false);
useEffect(() => {
function toggleFlight(e: KeyboardEvent) {
if (e.code === "KeyF") {
setFlying(f => !f);
}
}
const source = domElement || window;
source.addEventListener("keyup", toggleFlight as any);
return () => source.removeEventListener("keyup", toggleFlight as any);
}, [domElement]);
useFrame(() => {
if (!getKeys || !flying || !cref.current) return;
const { jump, run } = isInsideKeyboardControls ? getKeys() : {};
if (jump) cref.current.applyImpulse({ x: 0, y: 0.05, z: 0 }, true);
if (run) cref.current.applyImpulse({ x: 0, y: -0.05, z: 0 }, true);
});
return <Ecctrl ref={cref as any} {...props} {...(flying ? Flying : null)} />;
}
Sandbox (convert from above TS to JS)
these 2 states are critical for many use cases
relevant resources: https://youtu.be/jxecc2IGlWA?si=PP8NB8Nu1-I1WJpJ https://www.youtube.com/watch?v=cIZaqeJd28Y
related to #109