Files
battle-royal-tetris/CLAUDE.md
T
jozamudi 4a49c76cdc Add hold piece feature
- Added holdPiece and canHold state to TetrisGame class
- Implemented hold() method to swap current piece with held piece
- Added player-hold socket event on server
- Added HOLD preview canvas showing held piece (grayed when unavailable)
- Added C key keyboard shortcut and touch button for hold
- Fixed canHold reset on piece spawn for proper swap functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 08:50:52 -07:00

2.8 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

# Server runs on http://localhost:3000 (or PORT env variable)

Architecture

Server-Client Model

  • Server (server/index.js): Express + Socket.io handles all game logic authoritatively

    • 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()
    • Tetromino definitions and board constants are duplicated on server
  • 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

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