Files
try-claudekit/CLAUDE.md
tiennm99 c0fe135ff0 docs: add CLAUDE.md, update README, add collision fix spec
Add CLAUDE.md with architecture overview and dev commands for future
Claude Code sessions. Update README with tech stack, project structure,
and how-to-play instructions. Add spec for fixing collision physics
tuning issues.
2026-04-12 10:48:50 +07:00

2.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

npm run dev          # Start Vite dev server (http://localhost:5173)
npm run build        # Production build to dist/
npm test             # Run all tests once
npm run test:watch   # Run tests in watch mode
npx vitest run src/fruits.test.js   # Run a single test file

No vite.config or vitest.config files — both use defaults.

Architecture

This is a Suika Game (watermelon merge puzzle) built with vanilla JavaScript + Matter.js + Canvas2D, bundled by Vite.

Module Orchestration

game.js is the central orchestrator. The Game class owns the physics engine and game state, delegating to specialized modules:

  • physics.js — Thin wrapper around Matter.js. Creates engine, walls, fruit bodies. Bodies are annotated with custom properties: fruitTier (0-10), removing (merge flag), dropTime (grace period timestamp).
  • merger.js — Listens to Matter.js collisionStart events. Queues merges into a pending array; flushMerges() is called by the game loop after Engine.update() to avoid mid-step world mutation. Receives addScore() callback to stay decoupled from game state.
  • renderer.js — Pure rendering: render(ctx, bodies, state) draws everything to Canvas2D with no side effects.
  • input.js — Mouse/touch event binding + clampX() utility that accounts for fruit radius to keep drops within container walls.
  • fruits.js — Static array of 11 fruit tiers. Only tiers 0-4 are randomly selected for dropping.
  • constants.js — Single source of truth for all dimensions, physics tuning, and timing values.

Key Patterns

  • Deferred merge processing: Collisions are queued during physics events, then flushed after the engine step completes. This prevents Matter.js internal state corruption.
  • Grace period: Newly dropped fruits have 1000ms immunity from game-over detection to prevent instant-loss on drops near the danger line.
  • State via callbacks: setupMergeHandler() receives getState() and addScore() callbacks rather than importing game state directly.

Testing

Tests are colocated (src/*.test.js) using Vitest with describe/it/expect. No mocking — tests use real Matter.js engine instances and pure function assertions. Physics integration tests step the engine 10-60 times and assert state changes.