feat: complete sentences mode with Star Wars effect and line transitions

- Implement two-line layout with Star Wars perspective (top line 80% size)
- Add smooth line transition animation when first line completes
- First line explodes independently, second line grows and moves down
- Fix space handling at line breaks (space included in first line)
- Ship stays centered for sentences mode
- Support punctuation input (commas, periods, exclamation, question marks)
- Reduce font size to 20px for better readability
- Set falling speed to 25 pixels/second for sentences
This commit is contained in:
2025-11-04 17:42:25 +00:00
parent 9ed9a0510c
commit d1de98793a
4 changed files with 185 additions and 53 deletions
+5 -3
View File
@@ -1,4 +1,4 @@
import { useState, useEffect } from "react";
import { useState, useEffect, useRef } from "react";
import type { GameManager, GameOptions, KeyLogEntry, FallingLetter, GameMode } from "../types";
import { useBoard } from "../useBoard";
import { useCursor } from "../useCursor";
@@ -11,6 +11,7 @@ export function useGame(
): GameManager {
const [keyLog, setKeyLog] = useState<KeyLogEntry[]>([]);
const [gameMode, setGameModeState] = useState<GameMode>(options?.initialGameMode ?? 'letters');
const gameModeRef = useRef<GameMode>(gameMode);
const boardManager = useBoard();
const cursorManager = useCursor();
@@ -18,7 +19,7 @@ export function useGame(
// Wrap renderBoard to include player position
const renderBoardWrapped = (letters: any = []) => {
boardManager.renderBoard(cursorManager.position(), letters, gameStatusManager.shipState, gameStatusManager.shipExplosionTime, gameMode);
boardManager.renderBoard(cursorManager.position(), letters, gameStatusManager.shipState, gameStatusManager.shipExplosionTime, gameModeRef.current);
};
// Game loop tick handler
@@ -28,7 +29,7 @@ export function useGame(
// For words/letters, auto-track to falling letters
// For sentences/paragraphs, keep ship centered
if (gameMode !== 'sentences' && gameMode !== 'paragraphs') {
if (gameModeRef.current !== 'sentences' && gameModeRef.current !== 'paragraphs') {
if (letters.length > 0) {
const letter = letters[0];
cursorManager.setTargetX(letter.x);
@@ -46,6 +47,7 @@ export function useGame(
// Update gameMode when it changes (without recreating gameStatus state)
useEffect(() => {
gameModeRef.current = gameMode;
gameStatusManager.setGameMode(gameMode);
}, [gameMode]);