-
-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feature request: flying and climbing states #111
Comments
hichemfantar
changed the title
feature request: isFlying and isClimbing states
feature request: flying and climbing states
Oct 6, 2024
Related to #29 too |
This is a flying POC I created. Press "F" to toggle flying mode. import { forwardRef, KeyboardEvent, useEffect, useImperativeHandle, 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 & {
forceFlying?: boolean;
domElement?: HTMLElement;
};
export default forwardRef(function EcctrlWithFlight(
{ forceFlying, domElement, ...props }: EcctrlWithFlightProps,
fref,
) {
const cref = useRef<RapierRigidBody | undefined>();
useImperativeHandle(fref, () => cref.current);
const lastImpulseTime = useRef<number | null>(null);
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(state => {
if (!getKeys || !(forceFlying ?? flying) || !cref.current || !isInsideKeyboardControls) return;
if (lastImpulseTime.current !== null && state.clock.getElapsedTime() - lastImpulseTime.current < 0.1) return;
const { jump, run } = getKeys();
if (lastImpulseTime.current === null && (jump || run)) {
// just started ascending or descending
lastImpulseTime.current = state.clock.getElapsedTime();
}
if (jump) {
cref.current.applyImpulse({ x: 0, y: 0.02, z: 0 }, true);
} else if (run) {
cref.current.applyImpulse({ x: 0, y: -0.02, z: 0 }, true);
} else {
lastImpulseTime.current = null;
}
});
return <Ecctrl ref={cref as any} {...props} {...((forceFlying ?? flying) ? Flying : null)} />;
}); Sandbox |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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
The text was updated successfully, but these errors were encountered: