From 68a2e66b9eb5c0cad28429a89d28bae672e41c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20R=C3=B6ssner?= Date: Sat, 2 Nov 2024 15:36:02 +1100 Subject: [PATCH] feat: add the ability to change replay speed --- app/play/[level]/page.tsx | 41 ++++++++++++++++++++++++++++----------- components/Visualizer.tsx | 9 +++++++-- components/ui/slider.tsx | 28 ++++++++++++++++++++++++++ constants/visualizer.ts | 2 +- package.json | 1 + renderer/Renderer.ts | 4 ++-- 6 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 components/ui/slider.tsx diff --git a/app/play/[level]/page.tsx b/app/play/[level]/page.tsx index 61c6b0d..f551949 100644 --- a/app/play/[level]/page.tsx +++ b/app/play/[level]/page.tsx @@ -10,6 +10,7 @@ import { Map } from "@/components/Map"; import { Page, PageTitle } from "@/components/Page"; import { Visualizer } from "@/components/Visualizer"; import { Button } from "@/components/ui/button"; +import { Slider } from "@/components/ui/slider"; import { Table, TableBody, @@ -19,6 +20,7 @@ import { TableRow, } from "@/components/ui/table"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { DEFAULT_REPLAY_SPEED } from "@/constants/visualizer"; import { api } from "@/convex/_generated/api"; import { ZombieSurvival } from "@/simulators/zombie-survival"; @@ -39,6 +41,7 @@ export default function PlayLevelPage({ const [landmineCount, setLandmineCount] = useState(0); const flags = useQuery(api.flags.getFlags); const [mode, setMode] = useState<"play" | "test">("play"); + const [replaySpeed, setReplaySpeed] = useState(DEFAULT_REPLAY_SPEED); // Initialize playerMap when map data is available useEffect(() => { @@ -242,6 +245,7 @@ export default function PlayLevelPage({ autoStart onReset={handleReset} onSimulationEnd={handleSimulationEnd} + replaySpeed={replaySpeed} /> {gameResult && (
)}
-
+
{!isSimulating ? ( <> - - +
+

Choose the speed (200ms to 2s)

+ { + setReplaySpeed(value[0]); + }} + /> +
+
+ + +
) : (
diff --git a/components/Visualizer.tsx b/components/Visualizer.tsx index 0c9a8e0..5ee18d0 100644 --- a/components/Visualizer.tsx +++ b/components/Visualizer.tsx @@ -1,6 +1,9 @@ import * as React from "react"; import { Button } from "@/components/ui/button"; -import { AUTO_REPLAY_SPEED, REPLAY_SPEED } from "@/constants/visualizer"; +import { + AUTO_REPLAY_SPEED, + DEFAULT_REPLAY_SPEED, +} from "@/constants/visualizer"; import { Renderer } from "@/renderer"; import { ZombieSurvival } from "@/simulators/zombie-survival"; @@ -12,6 +15,7 @@ export function Visualizer({ map, onReset, onSimulationEnd, + replaySpeed = DEFAULT_REPLAY_SPEED, }: { autoReplay?: boolean; autoStart?: boolean; @@ -20,6 +24,7 @@ export function Visualizer({ map: string[][]; onReset?: () => unknown; onSimulationEnd?: (isWin: boolean) => unknown; + replaySpeed?: number; }) { const simulator = React.useRef(new ZombieSurvival(map)); const renderer = React.useRef(null); @@ -79,7 +84,7 @@ export function Visualizer({ if (onSimulationEnd) { onSimulationEnd(!simulator.current.getPlayer().dead()); } - }, REPLAY_SPEED); + }, replaySpeed); } React.useEffect(() => { diff --git a/components/ui/slider.tsx b/components/ui/slider.tsx new file mode 100644 index 0000000..ab19d57 --- /dev/null +++ b/components/ui/slider.tsx @@ -0,0 +1,28 @@ +"use client" + +import * as React from "react" +import * as SliderPrimitive from "@radix-ui/react-slider" + +import { cn } from "@/lib/utils" + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)) +Slider.displayName = SliderPrimitive.Root.displayName + +export { Slider } diff --git a/constants/visualizer.ts b/constants/visualizer.ts index c5083b4..653687c 100644 --- a/constants/visualizer.ts +++ b/constants/visualizer.ts @@ -1,2 +1,2 @@ export const AUTO_REPLAY_SPEED = 1_500; -export const REPLAY_SPEED = 600; +export const DEFAULT_REPLAY_SPEED = 600; diff --git a/package.json b/package.json index 58301a0..3e028c7 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.1.2", + "@radix-ui/react-slider": "^1.2.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.1", "@radix-ui/react-toast": "^1.2.1", diff --git a/renderer/Renderer.ts b/renderer/Renderer.ts index 2175bbc..042d42d 100644 --- a/renderer/Renderer.ts +++ b/renderer/Renderer.ts @@ -1,7 +1,7 @@ import { assets, loadAssets } from "./Assets"; import { type RendererEffect, RendererEffectType } from "./Effect"; import { RendererItem } from "./Item"; -import { REPLAY_SPEED } from "@/constants/visualizer"; +import { DEFAULT_REPLAY_SPEED } from "@/constants/visualizer"; import { type Entity, EntityType, @@ -223,7 +223,7 @@ export class Renderer { effects.push({ type: RendererEffectType.Move, - duration: REPLAY_SPEED, + duration: DEFAULT_REPLAY_SPEED, startedAt: Date.now(), to: { x: to.x * this.cellSize,