feat: implement game modes system with letters and words support

- Add GameMode type: 'letters' | 'words' | 'sentences' | 'paragraphs'
- Add gameMode option to GameOptions (defaults to 'letters')
- Create wordLists.ts with curated word lists for each mode
- Update FallingLetter type to track:
  - fullText: complete word/sentence/paragraph
  - charIndex: current character progress in word
- Modify word spawning to pick from mode-specific word list
- Update handleTypedLetter to support multi-character typed sequences:
  - Track progress through word (charIndex)
  - Advance to next character when correct
  - Show complete word only when fully typed
- Enhanced canvas rendering with color-coded progress:
  - Green: completed characters
  - Yellow: current character being typed
  - White: remaining characters
- Add mode selector buttons to example app
- Default to 'words' mode in example for testing
- Full TypeScript support for all modes
This commit is contained in:
2025-11-03 23:10:00 +00:00
parent 7ee42a8dc1
commit 662557c933
7 changed files with 138 additions and 26 deletions
+25 -3
View File
@@ -1,9 +1,11 @@
import { useGame } from "@vimazing/typing-chud";
import { useState } from "react";
import { useGame, type GameMode } from "@vimazing/typing-chud";
import "@vimazing/typing-chud/game.css";
import { useKeyBindings } from "./useKeyBindings";
function App() {
const gameManager = useGame({}, useKeyBindings);
const [gameMode, setGameMode] = useState<GameMode>("words");
const gameManager = useGame({ gameMode }, useKeyBindings);
const { containerRef, gameStatus, scoreManager } = gameManager;
const formatTime = (ms: number) => {
@@ -15,7 +17,27 @@ function App() {
return (
<div className="relative mx-auto my-4 w-fit space-y-4">
<h1 className="text-2xl font-bold text-center">Typing Chud</h1>
<div className="space-y-2">
<h1 className="text-2xl font-bold text-center">Typing Chud</h1>
<div className="flex gap-2 justify-center text-sm">
{(['letters', 'words', 'sentences', 'paragraphs'] as const).map((mode) => (
<button
key={mode}
onClick={() => {
setGameMode(mode);
gameManager.quitGame();
}}
className={`px-3 py-1 rounded capitalize font-medium transition ${
gameMode === mode
? 'bg-blue-600 text-white'
: 'bg-muted text-foreground hover:bg-blue-500 hover:text-white'
}`}
>
{mode}
</button>
))}
</div>
</div>
<div className="grid grid-cols-6 gap-2 justify-center text-sm font-mono">
<div className="px-3 py-1 bg-muted rounded">