feat(phase1.2b): implement Nokia-style key buffering system

- Add nextDirectionRef to buffer player input
- Update changeDirection() to queue input instead of immediate execution
- Add applyBufferedDirection() to safely apply buffered input
- Buffer prevents 180° reversals for safe turns
- Call applyBufferedDirection() after each successful move in game loop
- Remove collision grace period - no longer needed with key buffering
- Remove collisionGracePeriodRef and related logic
- Clean up all console.log statements from useGameStatus
- Game now feels responsive at high speeds
- Allows pre-emptive turning on board edges (Nokia Snake style)
- Build and example app work correctly
This commit is contained in:
2025-10-30 22:39:21 +00:00
parent f9cd9c60e7
commit 762bc86878
3 changed files with 30 additions and 36 deletions
+22
View File
@@ -13,6 +13,7 @@ export function useCursor(
const [direction, setDirection] = useState<Direction>("up");
const directionRef = useRef<Direction>("up");
const lastMovedDirectionRef = useRef<Direction>("up");
const nextDirectionRef = useRef<Direction | null>(null);
const initSnake = () => {
const centerR = Math.floor(rows / 2);
@@ -103,9 +104,29 @@ export function useCursor(
right: "left",
};
// Buffer the direction instead of applying immediately
// Only buffer if it's not a 180° reversal of the last MOVED direction
if (opposites[lastMovedDirectionRef.current] !== newDirection) {
nextDirectionRef.current = newDirection;
}
};
const applyBufferedDirection = () => {
if (nextDirectionRef.current === null) return;
const newDirection = nextDirectionRef.current;
const opposites: Record<Direction, Direction> = {
up: "down",
down: "up",
left: "right",
right: "left",
};
// Apply buffer only if still valid (not 180° reversal)
if (opposites[lastMovedDirectionRef.current] !== newDirection) {
setDirection(newDirection);
directionRef.current = newDirection;
nextDirectionRef.current = null;
}
};
@@ -237,6 +258,7 @@ export function useCursor(
initSnake,
clearSnake,
changeDirection,
applyBufferedDirection,
moveSnake,
renderSnake,
};