|
| 1 | +# Project Architecture |
| 2 | + |
| 3 | +## Tech Stack |
| 4 | + |
| 5 | +| Category | Technology | Version | Purpose | |
| 6 | +|----------|-----------|---------|---------| |
| 7 | +| Framework | Next.js | 14.x | App Router SSR/SSG | |
| 8 | +| UI | React | 18.x | Component-based UI | |
| 9 | +| Rendering | Pixi.js | 7.x | WebGL 2D tile rendering | |
| 10 | +| Rendering Bindings | @pixi/react | 7.x | React-Pixi integration | |
| 11 | +| State Management | Zustand | 5.x | Lightweight global state | |
| 12 | +| Graph Visualization | @xyflow/react | 12.x | Skill tree / Sitemap | |
| 13 | +| Markdown | Showdown | 2.x | Documentation rendering | |
| 14 | +| Styling | SASS | 1.x | SCSS modules | |
| 15 | +| Tile Processing | WASM (Rust) | — | High-performance hex→tile conversion | |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## Directory Structure |
| 20 | + |
| 21 | +``` |
| 22 | +src/ |
| 23 | +├── app/ # Next.js pages |
| 24 | +│ ├── page.tsx # Home (landing page) |
| 25 | +│ ├── layout.tsx # Root layout |
| 26 | +│ ├── play/ # Game page |
| 27 | +│ │ ├── page.tsx # Game orchestrator |
| 28 | +│ │ ├── layout.tsx # Play layout |
| 29 | +│ │ └── constants.ts # RENDER_RANGE, WS_URL, etc. |
| 30 | +│ ├── documents/ # Documentation pages |
| 31 | +│ ├── robots.ts # SEO robots.txt |
| 32 | +│ └── sitemap.ts # Sitemap XML |
| 33 | +│ |
| 34 | +├── components/ # React components |
| 35 | +│ ├── canvas/ # Canvas orchestrator |
| 36 | +│ ├── tilemap/ # Pixi.js tile renderer |
| 37 | +│ ├── canvasDashboard/ # Zoom/stats UI |
| 38 | +│ ├── skilltree/ # Skill tree (ReactFlow) |
| 39 | +│ ├── chat/ # Chat overlay |
| 40 | +│ ├── scoreboard/ # Ranking display |
| 41 | +│ ├── inactive/ # Revive countdown |
| 42 | +│ └── ... |
| 43 | +│ |
| 44 | +├── hooks/ # Custom hooks |
| 45 | +│ ├── useMessageHandler # WebSocket message routing |
| 46 | +│ ├── useTileProcessing # hex → Uint8Array conversion |
| 47 | +│ ├── useTileViewport # Viewport calc + SET_WINDOW |
| 48 | +│ ├── useInputHandlers # Mouse/touch input |
| 49 | +│ ├── useMovement # A* pathfinding + cursor animation |
| 50 | +│ ├── useCursorRenderer # Cursor/path Canvas 2D rendering |
| 51 | +│ ├── useExplosionManager # Explosion state management |
| 52 | +│ ├── useShockwaveAnimation # Explosion animation (RAF) |
| 53 | +│ ├── useSkillTree # Skill tree logic |
| 54 | +│ ├── useTilemapTextures # Pixi texture creation/caching |
| 55 | +│ └── useScreenSize # Window size tracking |
| 56 | +│ |
| 57 | +├── store/ # Zustand state stores |
| 58 | +│ ├── websocketStore # WebSocket connection state |
| 59 | +│ ├── tileStore # Tile grid + view bounds |
| 60 | +│ ├── cursorStore # Cursor position/zoom/score |
| 61 | +│ ├── interactionStore # Click position/animation |
| 62 | +│ ├── skillTreeStore # Purchased skills list |
| 63 | +│ └── rankingStore # Leaderboard |
| 64 | +│ |
| 65 | +├── utils/ # Utilities |
| 66 | +│ ├── tileGrid.ts # TileGrid class (Uint8Array) |
| 67 | +│ ├── tileCache.ts # World-coordinate LRU cache |
| 68 | +│ ├── wasmTileEngine.ts # WASM module loader |
| 69 | +│ ├── tiles.ts # Hex parsing LUT (vectorized) |
| 70 | +│ ├── aStar.ts # A* pathfinding algorithm |
| 71 | +│ ├── pixiSpritePool.ts # Sprite object pool |
| 72 | +│ ├── canvas.ts # Canvas drawing helpers |
| 73 | +│ └── makePath2d.ts # SVG → Path2D converter |
| 74 | +│ |
| 75 | +├── types/ # TypeScript type definitions |
| 76 | +│ ├── message.ts # WebSocket protocol types |
| 77 | +│ ├── canvas.ts # Rendering types |
| 78 | +│ ├── position.ts # Coordinate/direction types |
| 79 | +│ └── ... |
| 80 | +│ |
| 81 | +├── constants/ # Global constants |
| 82 | +│ └── cursor.ts # Cursor colors, 8-way offsets |
| 83 | +│ |
| 84 | +├── assets/ # SVG vector paths |
| 85 | +│ └── renderPaths.json # Tile/cursor/flag/bomb vectors |
| 86 | +│ |
| 87 | +└── wasm-pkg/ # WASM bindings (compiled from Rust) |
| 88 | + └── minesweeper_tile_engine.wasm |
| 89 | +``` |
| 90 | + |
| 91 | +--- |
| 92 | + |
| 93 | +## Zustand State Management |
| 94 | + |
| 95 | +``` |
| 96 | +┌──────────────────────────────────────┐ |
| 97 | +│ Zustand Stores │ |
| 98 | +├──────────────────────────────────────┤ |
| 99 | +│ websocketStore → socket, msg buffer │ |
| 100 | +│ tileStore → tile grid, bounds │ |
| 101 | +│ cursorStore → position, zoom │ |
| 102 | +│ interactionStore→ click, animation │ |
| 103 | +│ skillTreeStore → purchased skills │ |
| 104 | +│ rankingStore → ranking data │ |
| 105 | +└──────────────────────────────────────┘ |
| 106 | + ↑ (setters) ↓ (selectors) |
| 107 | + Hooks/Events React Components |
| 108 | +``` |
| 109 | + |
| 110 | +**Unidirectional data flow:** |
| 111 | +1. WebSocket event → `useMessageHandler` reads store state |
| 112 | +2. Store setter called (e.g., `applyTileChanges`) |
| 113 | +3. Subscribed components re-render |
| 114 | +4. Components read fresh store state |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Module Responsibilities |
| 119 | + |
| 120 | +### Hooks |
| 121 | + |
| 122 | +| Hook | Responsibility | |
| 123 | +|------|---------------| |
| 124 | +| `useMessageHandler` | Routes incoming WebSocket messages to event-specific handlers | |
| 125 | +| `useTileProcessing` | Converts hex-encoded tile data to TileGrid (Uint8Array); WASM-first, JS fallback | |
| 126 | +| `useTileViewport` | Calculates viewport bounds from zoom & cursor; debounces SET_WINDOW requests | |
| 127 | +| `useInputHandlers` | Detects left-click, right-click, long-press and triggers tile interactions | |
| 128 | +| `useMovement` | A* pathfinding, animates cursor along path, sends MOVE events | |
| 129 | +| `useCursorRenderer` | Draws player cursor, other cursors, and path lines on Canvas 2D | |
| 130 | +| `useExplosionManager` | Tracks active explosions (position, startTime, ID) | |
| 131 | +| `useShockwaveAnimation` | RAF loop for explosion animation (flash, rays, rings, sparks) | |
| 132 | +| `useSkillTree` | Manages ReactFlow nodes/edges, skill purchase, speed calculation | |
| 133 | +| `useTilemapTextures` | Pre-renders number textures + SVG assets as Pixi Textures | |
| 134 | +| `useScreenSize` | Detects window resize events, returns viewport dimensions | |
| 135 | + |
| 136 | +### Stores |
| 137 | + |
| 138 | +| Store | Managed State | |
| 139 | +|-------|--------------| |
| 140 | +| `websocketStore` | Socket object, isOpen, message buffer, binary message, connect/disconnect/sendMessage | |
| 141 | +| `tileStore` | tiles (TileGrid), renderTiles, startPoint/endPoint, tileSize, padtiles/applyChanges | |
| 142 | +| `cursorStore` | Player: id, position, color, zoom, score, items; Other users' cursor list | |
| 143 | +| `interactionStore` | Click position (x, y, content), movecost, useAnimation toggle | |
| 144 | +| `skillTreeStore` | purchasedSkills array | |
| 145 | +| `rankingStore` | Leaderboard rankings | |
| 146 | + |
| 147 | +### Key Components |
| 148 | + |
| 149 | +| Component | Role | |
| 150 | +|-----------|------| |
| 151 | +| `canvas/` | Orchestrator: coordinates tilemap, cursor rendering, input, animations | |
| 152 | +| `tilemap/` | Pixi Stage + sprite pools (bg, closed, boom, flag, number layers) | |
| 153 | +| `canvasDashboard/` | Zoom buttons, score/bomb display, animation/bomb mode toggles | |
| 154 | +| `skilltree/` | ReactFlow graph + skill info panel + purchase button | |
| 155 | + |
| 156 | +--- |
| 157 | + |
| 158 | +## Performance Optimizations |
| 159 | + |
| 160 | +| Technique | Description | |
| 161 | +|-----------|-------------| |
| 162 | +| Sprite Pooling | Reuse Pixi sprites instead of create/destroy per frame | |
| 163 | +| Flat Uint8Array | O(1) native memcpy tile copy via `Uint8Array.slice()` | |
| 164 | +| Vectorized LUT | 16-bit hex→tile type O(1) conversion without branching | |
| 165 | +| WASM Processing | Hex tile decoding 10-100x faster than JS | |
| 166 | +| RAF Loop | Smooth 60fps animations without blocking main thread | |
| 167 | +| Texture Caching | Pre-render number textures + SVG assets once at startup | |
| 168 | +| Concurrency Limiter | Max 8 concurrent GPU operations to prevent stalls | |
| 169 | +| LRU Tile Cache | World-coordinate cache for instant restore on revisit | |
| 170 | +| SET_WINDOW Debounce | 200ms debounce to reduce server request flood | |
| 171 | +| A* Early Exit | Adjacent tiles bypass full pathfinding | |
0 commit comments