A browser-based multiplayer real-time strategy (RTS) game inspired by the classics of the genre (Age of Empires / Age of Mythology): resource gathering, base building, advancing through the ages, training units, and combat. All content is original — art and soundtrack generated by AI, with custom code and balancing. An open source project, made for fun with the help of AI.
🎮 Play now: playageofai.com (live demo — may be offline when the server isn't running)
Runs 100% in the browser, on an isometric 2D Canvas. No downloads, no plugins.
🌍 Languages: the whole game — menus, in-game HUD, and messages — is available in English, Portuguese, and Spanish. It's auto-detected by your region and can be switched anytime from the in-game Options menu (the gear icon).
- Node.js 20+
- npm 10+
npm install
# Terminal 1 — server (WebSocket on port 8080)
npm run dev:server
# Terminal 2 — client (Vite on port 5199)
npm run dev:clientWindows shortcut: double-click iniciar.bat — it installs dependencies (first time), starts the server and client, and opens the game in your browser.
Open http://localhost:5199 in two or more tabs/machines (2 players minimum) — or play solo against a bot (add an AI opponent in the room). Create a room, mark yourself "Ready", and the host starts the match.
You can expose the game publicly with a Cloudflare Tunnel (HTTPS, no need to open a port on your router). There are two ways:
- Quick (temporary link): double-click
jogar-online.bat→ generates ahttps://…trycloudflare.comlink (changes each run). - Fixed domain (production mode): run
configurar-dominio.batonce, then usejogar-online-fixo.bat→ serves the pre-built game on your own domain, always at the same address.
Full walkthrough (including hosting on a 24/7 Android phone via Termux) in DEPLOY.md.
npm run typecheck # type-check server + client
npm run build # production build of the client (client/dist)
npm run smoke # E2E test: starts the server and simulates a match with 2 WebSocket clientsshared/ Shared contract (pure TypeScript, no dependencies)
├─ types.ts — entity and snapshot types
├─ constants.ts — balancing (costs, HP, speeds, map, ticks)
└─ protocol.ts — ClientMessage/ServerMessage messages (JSON over WebSocket)
server/ Node.js + TypeScript + ws backend — AUTHORITATIVE SERVER
├─ HTTP: serves the built client (client/dist) in production
├─ Lobby: rooms, ready-check, chat, host migration
└─ Simulation: 10 ticks/s loop, A* pathfinding,
state machines (gather → drop-off, building, combat),
all commands validated on the server
client/ Vite + TypeScript + Canvas 2D frontend (dimetric isometric 2:1)
├─ DOM screens: name → lobby → room → game → game over
├─ Sprite rendering (AI-generated art) + interpolation between snapshots
└─ HUD: resources, population, minimap, selection and action panels
- WebSocket (
ws) for real-time bidirectional communication in the browser. - Authoritative server: the client only sends intents (
move,gather,build,train,attack…); all simulation and validation happen on the server — a modified client can't affect the game state. - Full snapshots at 5 Hz with visual interpolation: simple, robust (a dropped message can't corrupt state), and sufficient for the match size.
- Monorepo with a
sharedpackage: a single place defines the protocol and balancing; server and client never diverge silently.
| Action | Control |
|---|---|
| Select | Left click / box drag (Shift adds) |
| Contextual command | Right click (move, gather, attack, build) |
| Camera | WASD / arrows, middle-button drag, wheel = zoom |
| Center on Town Center | H |
| Options (volume, resolution, language) | gear icon in the corner |
| Chat | Enter |
| Cancel selection/placement | Esc |
- Resources: food, wood, gold, stone — villagers gather and drop them off at the Town Center.
- Ages: advance by constructing buildings and gathering resources, unlocking new units and structures.
- Victory: destroy all enemy Town Centers.
Contributions are very welcome — this is a hobby project, open to anyone who wants to help make it better. Open an issue with ideas/bugs or send a pull request. 🙂
Note: the source-code comments are currently written in Portuguese. All identifiers (variables, functions, types) are in English, and the docs (this README + DEPLOY.md) are in English.
MIT — use, modify, and share freely.