Skip to content

Latest commit

ย 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿƒ Open Poker

An open-source Balatro clone that runs entirely in the browser.

Built with TypeScript, Three.js, Vite, GSAP, and Howler. Fast to run, deterministic to debug, and friendly to tinker with.

Play the demo on itch.io

๐Ÿš€ Quick start โ€ข ๐ŸŽฎ Gameplay โ€ข โœจ Features โ€ข ๐Ÿงช Testing โ€ข ๐Ÿค Contributing

Open Poker gameplay example

Disclaimer: This is a fan-made, non-commercial open-source project. It is not affiliated with or endorsed by LocalThunk or Playstack, the creators of Balatro. All original Balatro content, design, and trademarks belong to their respective owners.

๐Ÿ’ก What is this?

Open Poker is a faithful browser-based clone of Balatro โ€” the award-winning poker roguelike by LocalThunk. Balatro is a game where you play poker hands against escalating score targets, using jokers and card modifiers to build powerful, chain-reacting scoring combos.

This project reimplements Balatro's core mechanics from scratch in TypeScript, keeping gameplay simulation cleanly separated from rendering so rules can evolve safely while the 3D table, card effects, audio, and UI get polished.

๐ŸŽฎ Playable loop ๐Ÿง  Deterministic core ๐Ÿ› ๏ธ Hackable stack
Play hands, discard cards, beat blinds, and chase score targets. Seeded runs and snapshots make bugs easier to reproduce. TypeScript, Three.js, Vite, Vitest, Playwright, GSAP, and Howler.

๐ŸŽฎ Gameplay

Open Poker replicates Balatro's core loop:

  1. Deal โ€” 8 cards are dealt from a standard 52-card deck.
  2. Select & Play โ€” Choose up to 5 cards to play as a poker hand.
  3. Score โ€” The hand scores (base chips + card chips) ร— multiplier. Beat the blind's target score to advance.
  4. Discard โ€” Optionally discard up to 3 cards per round to fish for better hands.
  5. Progress โ€” Clear Small Blind โ†’ Big Blind โ†’ Boss Blind to advance the ante, increasing score targets.

Scoring formula

Balatro's scoring works differently from standard poker โ€” only scoring cards contribute chips:

Score = (Hand Base Chips + ฮฃ scoring card chips) ร— (Hand Base Mult + modifiers)

For example, a Pair scores only the two matching cards' chip values. Straights, Flushes, Full Houses, and higher hands score all 5 cards.

Hand types (all 12 Balatro hands implemented)

Hand Base Chips Base Mult
High Card 5 1
Pair 10 2
Two Pair 20 2
Three of a Kind 30 3
Straight 30 4
Flush 35 4
Full House 40 4
Four of a Kind 60 7
Straight Flush 100 8
Five of a Kind 120 12
Flush House 140 14
Flush Five 160 16

Five of a Kind, Flush House, and Flush Five are Balatro-exclusive hand types not found in standard poker.

Ante curve

Score targets escalate across 8 antes, following Balatro's progression: 300 โ†’ 800 โ†’ 2 000 โ†’ 5 000 โ†’ 11 000 โ†’ 20 000 โ†’ 35 000 โ†’ 50 000.

โœจ Features

Implemented

  • ๐Ÿƒ All 12 Balatro hand types evaluated and scored correctly.
  • ๐Ÿ’ฏ Chips ร— Mult scoring โ€” only scoring cards contribute chips, matching Balatro's exact rules.
  • ๐Ÿ“ˆ Hand levelling โ€” each hand type tracks its own level, chips, and mult (upgradeable via Planet cards in a future shop system).
  • ๐ŸŽฒ Seeded runs โ€” fully deterministic with antes, blinds, hands, discards, deck state, and score targets.
  • ๐Ÿƒ Card enhancements โ€” Bonus (+30 chips), Mult (+4 mult), Wild (any suit), Glass (ร—2 mult, 1/4 break chance), Steel (ร—1.5 while in hand), Stone (+50 chips, no rank/suit), Gold ($3 at round end), Lucky (random mult/money).
  • ๐Ÿ”– Card seals โ€” Gold, Red, Blue, and Purple seals.
  • โœจ Card editions โ€” Foil (+50 chips), Holographic (+10 mult), Polychrome (ร—1.5 mult), Negative.
  • ๐Ÿช„ 3D table and card rendering powered by Three.js.
  • ๐Ÿ’ฅ Scoring popups with animated Chips ร— Mult readouts and win/lose overlays.
  • ๐ŸŽจ Optional art overrides โ€” drop custom sprites into public/art/ to replace placeholder art.
  • ๐Ÿ”Š Procedural audio via Howler and a custom synth engine.
  • ๐Ÿงช Deterministic snapshots โ€” save and restore full run state for debugging and tests.
  • ๐Ÿ“Š Debug overlay (F3 or `) with seed, phase, blind, ante, score, FPS, and renderer metrics.

Planned / not yet implemented

  • ๐Ÿƒ Joker system (passive effects that chain during scoring).
  • ๐Ÿ›’ Shop loop (buy/sell jokers, consumables, card packs between rounds).
  • ๐ŸŽด Consumables (Tarot cards, Planet cards, Spectral cards).
  • ๐Ÿ‘๏ธ Boss blind special effects.
  • ๐Ÿ“ฑ Mobile / touch support.

๐Ÿš€ Quick start

Requirements

  • Node.js 20+
  • npm

Install and run

npm install
npm run dev

The Vite dev server starts at:

http://localhost:5173

Controls

Action Key / Click
Select / deselect card Click card
Play selected cards Enter or Play button
Discard selected cards Backspace or Discard button
Restart run R
Toggle debug overlay F3 or `

๐Ÿงฐ Scripts

Command What it does
npm run dev Start the Vite dev server with hot reload.
npm run typecheck Run TypeScript checks with --noEmit.
npm run test Run unit tests once.
npm run test:watch Run unit tests in watch mode.
npm run test:coverage Run unit tests with v8 coverage.
npm run test:smoke Run the Playwright browser smoke playtest.
npm run build Typecheck and create a production build.
npm run build:itch Create an itch.io-ready production build and open-poker-itch.zip.
npm run check Run the full quality gate: typecheck + coverage + build.
npm run preview Serve the production build locally.
npm run gen-art Generate placeholder art into public/art/.

Itch.io HTML5 build

Live demo: alexis-labs.itch.io/open-poker

Run npm run build:itch, then upload open-poker-itch.zip as an HTML5 game. The package keeps index.html at the zip root and stores asset paths with / separators so itch.io can serve assets/ and art/ files correctly. The build uses relative asset paths and shows a splash loader until the packaged art and music have been fetched.

๐Ÿ—บ๏ธ Project map

src/
  main.ts              App bootstrap: state, render, input, and HUD.
  game/
    types.ts           Core domain types (cards, hands, run phases).
    cards.ts           Deck building, RNG, and shuffle utilities.
    pokerEngine.ts     Hand detection and Balatro-style scoring.
    gameState.ts       Run-level state machine (antes, blinds, phases).
  render/
    ThreeScene.ts      Three.js scene setup and card layout.
    CardObject.ts      3D card mesh with texture and animation.
    cardTextures.ts    Texture loading and art override resolution.
    Interaction.ts     Mouse / pointer event handling.
    Particles.ts       Particle effects for scoring feedback.
  audio/
    AudioManager.ts    Global audio singleton.
    musicEngine.ts     Procedural background music.
    synth.ts           Web Audio API synth primitives.
  input/
    actions.ts         Semantic action map and keyboard bindings.
public/
  art/                 Optional asset overrides: cards, backs, blinds, UI.
  examples/            Media used in docs.
tests/
  unit/                Vitest unit tests for game logic.
  smoke/               Playwright browser smoke tests.
docs/
  adr/                 Architecture decision records.

๐Ÿ—๏ธ Architecture

The project enforces a strict separation between simulation and rendering:

  • src/game/ โ€” Pure TypeScript, no DOM or Three.js imports. All game rules live here.
  • src/render/ โ€” Three.js rendering only. Reads from GameState; never mutates it directly.
  • src/audio/ โ€” Audio concerns only.
  • src/input/ โ€” Physical key bindings mapped to semantic InputAction values.

This boundary means the poker engine can be unit-tested headlessly at full speed, and the renderer can be swapped out without touching any rules. See docs/adr/0001-architecture-boundaries.md for the full contract.

๐Ÿงญ Deterministic debugging

Open Poker is designed to make bugs reproducible instead of mysterious.

  • GameState exposes toSnapshot(), loadSnapshot(), and reset(seed | snapshot).
  • A browser test bridge is available as window.__OPEN_POKER_TEST__ for automated smoke checks.
  • The debug panel (F3 / `) shows:
    • seed, phase, blind, and ante
    • score and economy counters
    • hand, deck, and discard counts
    • approximate FPS plus renderer draw/triangle metrics

๐Ÿงช Testing & CI

  • Unit tests (tests/unit/) validate hand evaluation, scoring math, and run flow transitions.
  • Coverage thresholds are enforced for src/game/ in vitest.config.ts.
  • GitHub Actions:
    • build.yml โ€” typecheck + test:coverage + build
    • playtest.yml โ€” Playwright smoke pass + HTML report artifact

โšก Performance budget

See docs/performance-budget.md.

Desktop-first targets:

  • 55+ FPS average during normal hand interactions.
  • Stable draw calls and responsive UI during scoring bursts.

๐Ÿค Contributing

Contributions are welcome! Start with CONTRIBUTING.md.

Good first areas:

  • ๐Ÿƒ Poker edge-case correctness.
  • โœจ HUD and interaction polish.
  • โ™ฟ Accessibility and responsive improvements.
  • ๐Ÿƒ Joker system and shop loop.
  • ๐ŸŽด Consumable cards (Tarot, Planet, Spectral).
  • ๐Ÿงฐ Test coverage and developer tooling.

See docs/good-first-issues.md for ready-to-pick starter tasks.

๐Ÿ“„ License

MIT. See LICENSE.


Open Poker is a fan project. If you enjoy this, please support the original โ€” buy Balatro.