A 1v1 turn-based card battler, drawn entirely in pixel art. Pure HTML5 canvas + vanilla JavaScript — no build step, no dependencies, no external assets. Every sprite, the font, and all sound effects are generated in code.
15 seconds of a turn against the AI. Watch it as a sharper MP4.
CardiHero is a personal demo project, made for learning and fun. It is not a commercial product. It is not affiliated with, endorsed by, or connected to Blizzard Entertainment or Hearthstone®. All artwork, characters and code in this repository are original and were made for this project. Hearthstone is a trademark of Blizzard Entertainment, Inc.
CardiHero is a personal demo project. The game was generated by Anthropic's Claude Opus 5.5 from a single prompt:
Create a 1-on-1 card game like Hearthstone. Just make it. As best you can. In pixel art style.
Open index.html in a browser, or serve the folder:
npx serve . # or: python3 -m http.server- Each hero starts at 30 health. Reduce the enemy hero to 0 to win.
- You gain a mana crystal every turn (max 10) and draw a card at the start of your turn.
- Drag a card from your hand onto the board to play it. Targeted spells turn into an arrow — drop it on a target.
- Drag from a glowing minion (or your armed hero) to an enemy to attack. You can also click the attacker, then click the target.
- Click your hero power (round button next to your hero) once per turn.
- Hover over anything to inspect it (tap on touch screens). Right-click or
Esccancels.Spaceends your turn,Mmutes.
- 4 heroes with unique hero powers and 30-card decks:
- Vela the Arcanist (mage) — Ember Spark: deal 1 damage.
- Brakka the Warlord (warrior) — Iron Skin: gain 2 armor.
- Aldric the Knight (paladin) — Reinforce: summon a 1/1 Recruit.
- Sylva the Ranger (hunter) — Sure Shot: 2 damage to the enemy hero.
- ~80 cards: minions, spells and weapons with Taunt, Charge, Rush, Divine Shield, Windfury, Stealth, Poisonous, Lifesteal, Freeze, Silence, Spell Damage, Battlecry, Deathrattle, auras and enrage.
- Full rules: mulligan, a Lucky Coin for the second player, fatigue, hand/board limits, overdraw burning, summoning sickness, taunt blocking, weapons with durability, armor.
- AI opponent that simulates every legal move one step ahead and picks the best (Normal / Easy).
- Animations: attack lunges, projectiles, particles, screen shake, floating damage numbers, enemy card reveals, turn banners.
- Chiptune sound effects synthesized with WebAudio.
- Pause menu with game speed (1x/2x/3x), sound toggle and concede.
| File | Purpose |
|---|---|
js/font.js |
Variable-width 5px bitmap font |
js/sprites.js |
Palette and hand-drawn 16x16 / 24x24 sprites (with palette-swapped variants) |
js/cards.js |
Card database, heroes, hero powers and decks |
js/engine.js |
Rules engine (JSON state, async actions with animation hooks) |
js/ai.js |
Greedy one-ply search AI |
js/audio.js |
Procedural sound effects |
js/render.js |
Drawing primitives, cards, minions, heroes |
js/ui.js |
Screens, input, animations and turn flow |
tests/sim.js |
Headless AI-vs-AI games to smoke-test the engine |
node tests/sim.js 200Plays 200 headless AI-vs-AI games across all hero matchups, checks invariants after every action, and prints win rates per hero.
MIT — see LICENSE.

