Aetheria — Fantasy Tower Defense
A small but fully playable Tower Defense game. Create your own adventurer,
collect champions through summons, deploy them to hold back waves of enemies,
and defeat the boss of each stage.
Built with Vite + React + TypeScript and a plain <canvas> for the board —
no game engine and no runtime libraries beyond React. All sprites, props,
terrain, sound effects and music are drawn or synthesized in code.
Run
npm install
npm run dev # start the dev server (http://localhost:5174)
npm run build # type-check + production build
npm run lint # eslint
npm run typecheck # tsc only
npm run champions # dev server opened on the champion stats sheet (#champions)
npm run enemies # dev server opened on the enemy stats sheet (#enemies)
npm run balance # headless balance simulator (tools/balance-sim)
npm run editor # content editor (http://localhost:5175), see "Content editor" below
How to play
- First launch opens the journal: create your adventurer's portrait, pick
a class (Blade, Bow or Magic) and sign your name. Your adventurer joins you
as a deployable hero champion. You also start with the Swordsman and
the Archer.
- The home desk is the menu: the map leads to Play, the crystal
ball to Summon and the journal to your adventurer, champions and
bestiary. Gems, patch notes and settings sit in the top-right corner.
- Summon more champions with 💎 gems (100 each). Once you own a champion
you keep it for good — no stacking. Summoning one you already own refunds
20% of the gems.
- Build your team of up to 6 champions in the journal's Champions pages;
only team members can be deployed in a stage.
- Play a stage: select a champion, click a free tile beside the path to
deploy it (spending 🪙 gold), then start each wave. Champions attack
automatically. Each champion has its own deploy limit per stage. Right-click
or press Esc to cancel a placement.
- Select a deployed champion to buy its in-stage upgrades with gold,
change its targeting (First / Last / Strongest) or sell it. Heroes level
up in battle and unlock an activated ability that costs mana.
- Kill enemies for gold and survive every wave on every path to win. Don't
let foes reach your castle. Clearing a stage unlocks the next and pays a 💎
gem reward the first time. Progress is saved automatically.
- Every stage, won or lost, earns mastery EXP to spend in each champion's
permanent skill tree (from the journal). Winning a stage also gives every
champion in your team 5 EXP per wave the stage had.
- Clear every stage of a chapter to unlock its endless mode: randomly
rolled waves that keep growing, with a boss every 5th wave worth 50 gems.
- Once your adventurer learns the armor node in their skill tree, endless
bosses may drop armor for them: a helmet, chestplate, leg piece or
boots in Common, Rare, Epic or Legendary. Every piece rolls random stats
(2 on Common and Rare, 3 on Epic and Legendary). Equip it in the
Armory from the journal; all four pieces of one set add its set bonus.
Unworn pieces can be salvaged for gems.
Currencies
- 💎 Gems — the persistent currency: earned from first clears and endless
bosses, spent on summons.
- ✨ Mastery EXP — earned by each champion from its kills in every stage, plus 5 per
wave for every team champion when a stage is won; spent in its skill tree.
- 🪙 Gold — a per-stage battle resource only: each stage starts you with a
fixed amount, slain enemies (and the Farmer) add more, and you spend it on
deploying and upgrading champions. It does not carry between stages.
Champions
- Swordsman, Archer, Crossbow — hit one enemy per attack.
- Spearman — a piercing line that strikes every enemy toward its target.
- Wizard — a gust of wind that homes in on one enemy.
- Elf — enchanted arrows that leap on to nearby enemies.
- Farmer — produces gold each wave instead of fighting.
- Bard — plays a tune that speeds up nearby champions' attacks.
- Your adventurer — a hero with a mana pool and an activated ability: the
Blade's dual swords, the Bow's arrow bursts or the Magic hero's exploding orbs.
Architecture
Strict one-directional layering (ui → application → domain, with engine a
self-contained sibling), so new content is mostly a data edit:
This is the beginning of the README. Read the rest at the original. Read the full README ↗