diff --git a/bun.lockb b/bun.lockb index 0d1c9aa..916ebc8 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/src/game/time.system.tsx b/src/game/time.system.tsx index 68f2799..0ac41c3 100644 --- a/src/game/time.system.tsx +++ b/src/game/time.system.tsx @@ -1,5 +1,5 @@ import { useRef } from "react"; -import { useAnimationFrame } from "~/hooks/useAnimationFrame"; +import { useTimeout } from "~/hooks/useTimeout"; import { useSettingsStore } from "~/store/settings.store"; import { useWorldStore } from "~/store/world.store"; import { TICK_MS } from "./const"; @@ -13,7 +13,7 @@ export function TimeSystem() { const paused = useSettingsStore((state) => state.paused); const speed = useSettingsStore((state) => state.speed); - useAnimationFrame((dt) => { + useTimeout((dt) => { if (paused) return; const time = timeRef.current + dt * speed; diff --git a/src/hooks/useAnimationFrame.ts b/src/hooks/useAnimationFrame.ts deleted file mode 100644 index f3a2b1f..0000000 --- a/src/hooks/useAnimationFrame.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { useEffect, useRef } from "react"; - -/** - * Inspired by react-ecs. - * @see https://github.com/dustinlacewell/react-ecs/blob/master/libs/core/src/hooks/useAnimationFrame.ts - */ -export const useAnimationFrame = ( - callback: (dt: number, time: number) => void, -) => { - const requestRef = useRef(null as unknown as number); - const previousTimeRef = useRef(null as unknown as number); - - const animate = (time: number) => { - // biome-ignore lint/suspicious/noDoubleEquals: null + undefined check - if (previousTimeRef.current != undefined) { - const deltaTime = time - previousTimeRef.current; - callback(deltaTime, time); - } - previousTimeRef.current = time; - requestRef.current = requestAnimationFrame(animate); - }; - - // biome-ignore lint/correctness/useExhaustiveDependencies: animate changes every render - useEffect(() => { - requestRef.current = requestAnimationFrame(animate); - return () => cancelAnimationFrame(requestRef.current); - }, [callback]); -}; diff --git a/src/hooks/useTimeout.ts b/src/hooks/useTimeout.ts new file mode 100644 index 0000000..f118a5d --- /dev/null +++ b/src/hooks/useTimeout.ts @@ -0,0 +1,38 @@ +import { useEffect, useRef } from "react"; + +export const useTimeout = ( + callback: (dt: number, time: number) => void, + interval: number = 1000 / 60 // 60 FPS +) => { + const timeoutRef = useRef(null); + const previousTimeRef = useRef(null); + const startTimeRef = useRef(null); + + const animate = () => { + const currentTime = performance.now(); + + if (startTimeRef.current === null) { + startTimeRef.current = currentTime; + } + + const time = currentTime - startTimeRef.current; + + if (previousTimeRef.current !== null) { + const deltaTime = time - previousTimeRef.current; + callback(deltaTime, time); + } + + previousTimeRef.current = time; + timeoutRef.current = setTimeout(animate, interval); + }; + + // biome-ignore lint/correctness/useExhaustiveDependencies: animate changes every render + useEffect(() => { + timeoutRef.current = setTimeout(animate, interval); + return () => { + if (timeoutRef.current !== null) { + clearTimeout(timeoutRef.current); + } + }; + }, [callback, interval]); +};