Files
battle-royal-tetris/CLAUDE.md
T
jozamudi aeacf9e68f Add performance improvements documentation and game-logic enhancements
- Add IMPROVEMENTS.md with detailed analysis of performance issues and bugs
- Update CLAUDE.md with negative Y overflow explanation
- Update README.md with socket events documentation
- Enhance game-logic.js with improved comments and validation
- Improve server/index.js with better documentation and edge case handling
2026-03-24 20:46:34 +00:00

3.7 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 authoritatively

    • index.js: Main server with socket.io event handlers
    • game-logic.js: Pure game logic functions (testable, no socket dependencies)
    • __tests__/: Jest test suite with 57 tests
    • Manages single global lobby with lobby.players Map
    • Game tick runs at 50ms intervals via gameTick()
    • Broadcasts state updates to all connected clients via broadcastState()
  • Client (public/js/): Vanilla JavaScript with module pattern

    • network.js: Socket.io client wrapper, manages player/game state caching
    • game.js: TetrisGame class for local game state (mirrors server)
    • renderer.js: TetrisRenderer class - Canvas rendering for all player boards
    • ui.js: UIManager class - screen transitions, DOM manipulation
    • app.js: Entry point, ties modules together, game loop via requestAnimationFrame

Game Flow

  1. Lobby: Players join global lobby via join-lobby socket event
  2. Ready: All players click READY; game starts when all ready (2-8 players)
  3. Game: Server authoritative - client inputs sent via socket, server broadcasts state
  4. Elimination: Player eliminated when piece locks at top or garbage fills board
  5. Victory: Game ends when 1 active player remains

Key Constants

  • BOARD_WIDTH = 10, BOARD_HEIGHT = 20, CELL_SIZE = 24
  • LOBBY_ROOM = 'global-lobby' - Socket.io room for all players
  • Garbage rules: 2 lines cleared -> 1 garbage row, 3 -> 2, 4 (Tetris) -> 4 rows

Piece Spawn & Negative Y Overflow

Pieces spawn at y = 0 (top of visible board). The coordinate system allows negative Y values as intentional overflow space:

  • Negative Y allowed: isValidPosition() only checks newY >= BOARD_HEIGHT, not newY < 0
  • Purpose: When garbage is received, pieces are pushed up (y decreases) into negative territory
  • Player survival: Player is NOT eliminated when piece goes negative — only when piece LOCKS with blocks in rows 0-1
  • Recovery: Piece drops naturally back into visible area; player can continue playing

This design gives players a buffer zone to recover from garbage attacks before elimination.

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