Skip to content
HordekillerPublic

About

A real-time multiplayer strategy game built with TypeScript, React, PixiJS, and WebSocket. Features ECS architecture for scalable gameplay, cross-platform support (mobile & desktop), and a modular codebase for easy expansion.

Topics

Resources

Code of conduct

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Repository files navigation

GamePad 4X TypeScript React PixiJS Node.js WebSocket ECS License

A real-time multiplayer 4X strategy game built for 2026 with cutting-edge technologies. Designed for cross-platform play (Android, Web, Desktop) with a mobile-first approach, ECS architecture, and WebSocket-based multiplayer.

🎯 Target Platforms: Android (APK/AAB via Capacitor), Web, Desktop 🌐 Play Now: https://gamepad4x.com (Coming Soon) 📱 Mobile Support: Full touch controls, collapsible UI, and 100dvh safe areas


✨ Features

Game Screenshot
  • 🌍 4X Gameplay: eXplore, eXpand, eXploit, eXterminate — turn-based strategy on a dynamic tile map
  • ⚡ Entity Component System: bitecs ECS for blazing-fast game state management
  • 👁️ Fog of War: Per-player visibility with GPU-accelerated shaders
  • 🔬 Tech Tree: 18 technologies across 3 tracks (Military, Economy, Science)
  • 🤝 Diplomacy: War, peace, alliances, and shared vision with real-time updates
  • 🤖 AI Opponents: 3 difficulty levels (Easy, Medium, Hard) with FSM-based decision making
  • 🎮 Matchmaking: ELO-based queue with dynamic rating range expansion
  • 🔄 Reconnection: Graceful reconnect with full state snapshot
  • 🌐 Multiplayer: WebSocket + msgpack binary protocol for low-latency communication
  • 📱 Mobile First: Responsive touch UI, collapsible sidebar, and 100dvh safe areas

🏗️ Architecture

Architecture Diagram
flowchart LR
    subgraph Client["📱 Client (Pixi.js + React)"]
        A["Web / Capacitor (Android)"] --> B["Pixi.js Renderer"]
        A --> C["React UI"]
    end
    
    subgraph Server["🖥️ Game Server (Node.js)"]
        D["WebSocket (msgpack)"] --> E["ECS Engine (bitecs)"]
        E --> F["Game Systems"]
        F --> G["AI (FSM)"]
        F --> H["Matchmaking (ELO)"]
    end
    
    subgraph DB["💾 Persistence"]
        I["JSON / Redis"]
    end
    
    Client <-->|WebSocket| Server
    Server <--> DB
Loading
Layer Technology Description
Client Rendering Pixi.js 8 (WebGL/Canvas2D) GPU-accelerated 2D rendering
Client UI React 19 (inline styles) Responsive, mobile-first UI
Network Protocol msgpack binary over WebSocket Low-latency, compact binary messages
Game Server Node.js 24 + ws library Event-driven, non-blocking I/O
ECS Engine bitecs 0.4 High-performance entity-component-system
Pathfinding fast-astar 2.0 (WASM-backed) Optimized A* pathfinding
Auth JWT + PBKDF2 password hashing Secure authentication
Mobile Wrapper Capacitor (Android APK/AAB) Native Android builds from web code
Deployment Docker + systemd Scalable, production-ready deployment

🔒 Security

Security
Layer Measure Description
WebSocket maxPayload: 64KB, maxClients tracking Prevents large payload attacks
Rate Limiting Per-IP sliding window (5/sec/IP) Mitigates brute-force and DDoS attacks
Connection Limit Max 10 concurrent connections per IP Prevents IP-based flooding
Password Hashing PBKDF2 (100k iterations, SHA-512, random salt) Secure password storage
Auth JWT tokens (24h expiry), username validation Stateless, time-limited authentication
Production Admin password detection, env validation Prevents misconfigurations
HTTPS/WSS SSL nginx config (client/nginx.ssl.conf) Encrypted communication

🚀 Quick Start

Prerequisites

Tool Version Installation Command
Node.js 24.x Download Node.js
pnpm 11.x npm install -g pnpm
Docker (Optional) Install Docker
# Clone the repository
git clone https://github.com/anomalyco/GamePad.git
cd GamePad

# Install dependencies
pnpm install

# Build shared package (required for client/server)
pnpm -C shared build

# Start development server (client + server)
pnpm dev
  • 🖥️ Server: ws://localhost:8080
  • 🌐 Client: http://localhost:3000
  • 📱 Mobile: Use http://<your-ip>:3000 on your phone (same network)

Production Build

pnpm build
pnpm start

Project Structure

├── shared/                  # Shared types, schemas, constants
│   ├── src/
│   │   ├── constants.ts     # Game balance, JWT config
│   │   ├── types.ts         # All game type definitions
│   │   ├── schemas.ts       # Zod validation schemas
│   │   ├── tech-tree.ts     # Tech tree definition
│   │   ├── units.ts         # Unit definitions
│   │   └── buildings.ts     # Building definitions
│   └── package.json
│
├── server/                  # Game server
│   ├── src/
│   │   ├── index.ts         # WebSocket server, rate limiting, tick loop
│   │   ├── game.ts          # Game class (orchestrates ECS, AI, tech, diplo)
│   │   ├── room.ts          # Room management
│   │   ├── auth.ts          # User auth (PBKDF2 + JWT)
│   │   ├── config.ts        # Environment config with validation
│   │   ├── logger.ts        # Structured logging
│   │   ├── matchmaking.ts   # ELO matchmaking queue
│   │   ├── rating.ts        # ELO rating system
│   │   ├── persistence.ts   # JSON state save/load
│   │   ├── mapgen.ts        # Procedural map generation
│   │   ├── ai-system.ts     # AI decision FSM (3 difficulties)
│   │   ├── game/
│   │   │   ├── ecs.ts       # ECS world, components, systems
│   │   │   ├── fog-system.ts      # Fog of war
│   │   │   ├── tech-system.ts     # Tech research & effects
│   │   │   ├── diplomacy-system.ts # Diplomatic relations
│   │   │   └── pathfinding.ts     # A* pathfinding (fast-astar)
│   │   └── admin/           # Admin panel (auth, store, RBAC)
│   ├── Dockerfile
│   └── package.json
│
├── client/                  # Web client
│   ├── src/
│   │   ├── index.tsx
│   │   ├── components/      # React components
│   │   │   ├── App.tsx      # Root, routing, responsive globals
│   │   │   ├── GameView.tsx # Main game view (mobile sidebar toggle)
│   │   │   ├── GameCanvas.tsx
│   │   │   ├── LoginPage.tsx
│   │   │   ├── ResourceBar.tsx
│   │   │   ├── MiniMap.tsx
│   │   │   ├── BuildingPanel.tsx
│   │   │   ├── TechTreeView.tsx
│   │   │   ├── DiplomacyView.tsx
│   │   │   └── NotificationToast.tsx
│   │   ├── pixi/            # Pixi.js renderer
│   │   │   ├── GameRenderer.ts
│   │   │   ├── FogRenderer.ts
│   │   │   └── TileRenderer.ts
│   │   ├── hooks/           # React hooks (useWebSocket)
│   │   └── audio/           # Sound manager
│   ├── Dockerfile
│   ├── nginx.conf           # HTTP nginx config
│   ├── nginx.ssl.conf       # HTTPS nginx config
│   └── package.json
│
├── deploy/                  # Production deployment
│   ├── gamepad.service      # systemd unit
│   └── docker-compose.prod.yml
│
├── docker-compose.yml       # Development compose
├── pnpm-workspace.yaml
├── tsconfig.base.json
├── .env.example
├── .nvmrc                   # Node 24
├── .node-version
├── .github/workflows/ci.yml # CI pipeline
└── Makefile

WebSocket Protocol

Messages are msgpack-encoded binary (not JSON). See shared/src/schemas.ts for Zod validation schemas.

Client → Server

Message Fields Description
auth token?: string Authenticate with JWT or "guest"
register username, password? Create account
login username, password Log in
join_room roomId?, difficulty? Join/create room; AI fill if difficulty set
action action: GameAction Submit game action
quick_match — Enter matchmaking queue
leave_matchmaking — Leave queue
reconnect roomId Reconnect to room
get_leaderboard — Get rankings
get_diplomacy — Get diplomacy state
leave_room — Leave current room
ping — Keep-alive

Server → Client

Message Description
welcome Connection established
auth_ok Auth successful + token
error Error with message
joined_room Room join confirmation + config
game_state Full state snapshot (periodic)
state_delta Incremental tick update
matchmaking_status Queue position + ETA
reconnect_info Full state for reconnection
leaderboard Player rankings
diplomacy_update Diplomatic relations state
pong Ping response
room_list Active rooms

Production Deployment

Docker Compose

# Development
docker compose up --build

# Production (with SSL reverse proxy)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up --build -d

VPS (systemd)

sudo cp deploy/gamepad.service /etc/systemd/system/
sudo systemctl enable gamepad
sudo systemctl start gamepad

Environment Variables

Copy .env.example → .env and configure:

Variable Default Description
WS_PORT 8080 Server port
WS_HOST 0.0.0.0 Bind address
NODE_ENV development production enables strict validation
TICK_INTERVAL_MS 1000 Game tick rate
MAX_TICKS 200 Max ticks before score victory
MAX_PLAYERS_PER_ROOM 4 Players per game
MAP_SIZE 64 Map tiles (NxN)
RATE_LIMIT_WINDOW 10000 Rate limit window (ms)
RATE_LIMIT_MAX 30 Max messages per window
ALLOWED_ORIGINS * CORS origins (comma-separated)
REDIS_URL `` Redis for multi-server pub/sub
ADMIN_JWT_SECRET — Admin JWT signing key
ADMIN_DEFAULT_PASSWORD — Default admin password

Android APK (Capacitor)

Build a native Android APK from the web client:

# Install Capacitor
pnpm add -D @capacitor/core @capacitor/cli @capacitor/android

# Build web assets
pnpm -C client build

# Init Capacitor
npx cap init GamePad com.gamepad4x.app
npx cap add android

# Sync web build to Android
npx cap sync

# Open in Android Studio (build APK/AAB from there)
npx cap open android

Or use Deploid for one-command APK builds:

npx deploid init
npx deploid package
npx deploid build

Requirements

  • Android SDK 34+
  • Java JDK 17+
  • Public HTTPS URL (for Play Store) or local testing on emulator

Graphics & Animation Guide

The game uses Pixi.js 8 for rendering. Recommended asset pipeline:

Asset Format Tool Notes
Unit sprites PNG sprite sheets (64x64) Aseprite / SpriteBrew 4-directional walk cycles
Tile terrain PNG tiles (32x32) Aseprite Grass, desert, water, mountain, forest
Building sprites PNG (48x48) Aseprite Factory, lab, refinery, turret, wall
UI icons PNG/SVG (24x24) Figma / Aseprite Resource icons, tech icons
Fog of war GPU shader GLSL Soft-edged visibility

Animation guidelines:

  • Pixel art: 8-12 FPS for retro feel
  • Movement: interpolate at 4 tiles/sec (configurable in GameRenderer.ts)
  • Camera: smooth pinch-zoom (0.3x–3x) with inertia
  • Attack effects: particle bursts (Pixi.js particle container)

Performance & Optimization

Concern Solution
WebSocket flooding Per-IP rate limiting (sliding window) + per-second connection cap
Memory exhaustion maxPayload: 64KB on WebSocket frames
DDoS connections Max 10 connections/IP, origin verification
Game tick CPU ECS delta tracking (only changed entities sent)
Render performance Pixi.js sprite batching, dirty-rect tracking
State size msgpack binary (40% smaller than JSON)
Idle rooms 5-minute idle timeout + periodic cleanup

Configuration Reference

Server (server/src/config.ts)

All config via environment variables. Production mode (NODE_ENV=production) requires explicit values for secrets.

Client (client/)

  • WebSocket URL: auto-detected from location.hostname
  • Canvas: full-viewport with dynamic DPI scaling
  • Mobile: collapsible sidebar, 100dvh viewport, touch controls


📜 License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A real-time multiplayer strategy game built with TypeScript, React, PixiJS, and WebSocket. Features ECS architecture for scalable gameplay, cross-platform support (mobile & desktop), and a modular codebase for easy expansion.

Topics

Resources

Code of conduct

Contributing

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages