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
100dvhsafe areas
- 🌍 4X Gameplay: eXplore, eXpand, eXploit, eXterminate — turn-based strategy on a dynamic tile map
- ⚡ Entity Component System:
bitecsECS 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
100dvhsafe areas
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
| 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 |
| 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 |
| 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>:3000on your phone (same network)
pnpm build
pnpm start├── 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
Messages are msgpack-encoded binary (not JSON). See shared/src/schemas.ts for Zod validation schemas.
| 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 |
| 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 |
# Development
docker compose up --build
# Production (with SSL reverse proxy)
docker compose -f docker-compose.yml -f docker-compose.prod.yml up --build -dsudo cp deploy/gamepad.service /etc/systemd/system/
sudo systemctl enable gamepad
sudo systemctl start gamepadCopy .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 |
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 androidOr use Deploid for one-command APK builds:
npx deploid init
npx deploid package
npx deploid build- Android SDK 34+
- Java JDK 17+
- Public HTTPS URL (for Play Store) or local testing on emulator
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)
| 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 |
All config via environment variables. Production mode (NODE_ENV=production) requires explicit values for secrets.
- WebSocket URL: auto-detected from
location.hostname - Canvas: full-viewport with dynamic DPI scaling
- Mobile: collapsible sidebar,
100dvhviewport, touch controls
This project is licensed under the MIT License - see the LICENSE file for details.