6d8ee7dda8
- Add test commands to CLAUDE.md and README.md - Update file structure to include game-logic.js and __tests__/ - Document Jest test suite with 57 tests
3.0 KiB
3.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Multiplayer Tetris Battle Royale game with 2-8 player real-time battles via WebSocket. Players clear rows to send garbage to opponents; last player standing wins.
Commands
# Install dependencies
cd server && npm install
# Start server
cd server && npm start
# or
cd server && node index.js
# Run tests
cd server && npm test
# Run tests with coverage
cd server && npm run test:coverage
# Server runs on http://localhost:3000 (or PORT env variable)
Architecture
Server-Client Model
-
Server (
server/): Express + Socket.io handles all game logic authoritativelyindex.js: Main server with socket.io event handlersgame-logic.js: Pure game logic functions (testable, no socket dependencies)__tests__/: Jest test suite with 57 tests- Manages single global lobby with
lobby.playersMap - Game tick runs at 50ms intervals via
gameTick() - Broadcasts state updates to all connected clients via
broadcastState()
-
Client (
public/js/): Vanilla JavaScript with module patternnetwork.js: Socket.io client wrapper, manages player/game state cachinggame.js:TetrisGameclass for local game state (mirrors server)renderer.js:TetrisRendererclass - Canvas rendering for all player boardsui.js:UIManagerclass - screen transitions, DOM manipulationapp.js: Entry point, ties modules together, game loop viarequestAnimationFrame
Game Flow
- Lobby: Players join global lobby via
join-lobbysocket event - Ready: All players click READY; game starts when all ready (2-8 players)
- Game: Server authoritative - client inputs sent via socket, server broadcasts state
- Elimination: Player eliminated when piece locks at top or garbage fills board
- Victory: Game ends when 1 active player remains
Key Constants
BOARD_WIDTH = 10,BOARD_HEIGHT = 20,CELL_SIZE = 24LOBBY_ROOM = 'global-lobby'- Socket.io room for all players- Garbage rules: 2 lines cleared -> 1 garbage row, 3 -> 2, 4 (Tetris) -> 4 rows
Socket Events
| Event | Direction | Payload |
|---|---|---|
join-lobby |
Client->Server | { playerName } |
ready |
Client->Server | - |
player-move |
Client->Server | { playerId, direction } |
player-rotate |
Client->Server | { playerId } |
player-drop |
Client->Server | { playerId, hard } |
player-joined |
Server->Client | { player, players } |
player-left |
Server->Client | { playerId, players } |
game-started |
Server->Client | { players, states } |
state-update |
Server->Client | states[] |
game-over |
Server->Client | { states } |
Rendering
- Each player gets a dynamically created board with canvas + info divs
renderer.setActivePlayer()marks current player's board as.main, others as.spectator- Battle grid layout classes:
.single-player,.two-players,.multi-player