- Vue 47.8%
- CSS 26.7%
- JavaScript 25.1%
- HTML 0.4%
| src | ||
| .gitignore | ||
| index.html | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| vite.config.js | ||
Honest Slot Machine
A Vue 3 slot machine simulator that shows the player both a traditional-looking animated reel display and an honest statistical gauge side-by-side. Every spin reveals where the RNG actually landed — no illusions.
The Concept
A single RNG determines every outcome. The slot-style reels can be composed to display near-misses — 2 matching symbols + 1 off — regardless of how far the actual result was from any win. Meanwhile, the honest gauge shows exactly where the random number landed and its true distance from each win tier.
- Deceptive Reels — Animated slot reels with configurable near-miss rate, tier-biased near-miss selection, and symbol clustering around the payline.
- Honest Gauge — A 1D number line with colored tier regions showing exactly where the random number landed.
Features
- 8-tier win system with fully adjustable thresholds and multipliers
- CSS-animated reels with staggered stop, suspense delays, and cubic-bezier ease-out
- Near-miss deception — configurable rate, tier-weighted target selection, and optional neighbor-symbol placement
- Honest position gauge — transparent 1D number line with tier regions and exact RNG marker
- Win celebrations — confetti, screen shake, flash overlays, glow rings, marquee light chase, rainbow cycling, and tiered announcer text (WINNER / BIG WIN / MEGA WIN / JACKPOT)
- Web Audio sound effects — procedurally generated digital/modern SFX: spin whoosh, reel stops, suspense arpeggio, 4 tiers of win fanfares, coin payouts, UI clicks, and global mute toggle (persisted)
- Mute toggle — speaker icon button, state saves to localStorage
- Auto-spin — preset counts (10/25/50/100) or custom, with remaining-counter display
- Fast mode — toggle for quicker reel animations
- Payout panels — flank the reels showing all tier symbols and multipliers, with winning tier highlighted
- Suspense mechanic — when the first two reels match, the third reel's stop is delayed proportionally to the tier (lower tiers = longer suspense)
- Full configuration panel — range max, starting balance, near-miss rate, neighbor rate, bias strength, bias decay, tier bias, per-tier range ends and multipliers, with live total RTP calculation
- Statistics panel — total spins, wagered, won, net result, realized RTP, win rate, biggest win, current/longest streaks, and per-tier hit counts with percentages
- Spin history — last 20 spins with number, bet, and win/loss
8-Tier Win System (defaults)
All thresholds and payouts are adjustable in the UI via the config panel.
| Tier | Symbol | Range (1–10000) | Payout (xBet) |
|---|---|---|---|
| 1 (Jackpot) | 🍒🍒🍒 | 1 | x500 |
| 2 | 7️⃣7️⃣7️⃣ | 2–6 | x80 |
| 3 | 💎💎💎 | 7–30 | x40 |
| 4 | ⭐⭐⭐ | 31–120 | x15 |
| 5 | 🔔🔔🔔 | 121–350 | x8 |
| 6 | 🍋🍋🍋 | 351–800 | x4 |
| 7 | 🍊🍊🍊 | 801–1500 | x2 |
| 8 | 💀💀💀 | 1501–3000 | x1 |
| Loss | (mixed) | 3001–10000 | 0 |
How the Deceptive Reels Work
Strip Generation
Each reel is a strip of 24 symbol positions. A target payline symbol is placed at position 12; the remaining 23 positions are filled using weighted random selection where positions closer to the target have a higher chance of drawing higher-rank symbols (via an exponential decay function). This creates a natural-looking cluster without explicit placement.
Composition Logic
- Win — All 3 reels stop on the winning symbol. Higher-value symbols are subtly more likely to appear adjacent to the payline.
- Near-miss loss (rate configurable, default 30%) — A random tier is selected (weighted toward higher tiers via a configurable tier-bias parameter). Two reels show that tier's symbol, one reel shows a random filler. Optionally (default 80%), the filler reel places the target symbol adjacent to the payline for a stronger near-miss illusion.
- Dead-spin loss — Three different low-value symbols on the payline. No near-miss.
CSS Animation
Each reel renders a 72-symbol strip (3 copies of the 24-position strip) inside a clipped viewport. Spin uses translateY with a cubic-bezier ease-out curve. Reels stagger via transition-delay (0ms / 200ms / 400ms). When the first two reels match, the third is delayed further based on the matched tier.
Tech Stack
- Vue 3 (Composition API,
<script setup>) - Vite (build tool)
- Zero backend — fully self-contained SPA
- Zero UI framework — custom CSS with neon glows, confetti, marquee lights, and gold-metallic slot-machine aesthetic
Project Structure
src/
├── main.js
├── App.vue
├── composables/
│ ├── useSlotMachine.js # RNG, balance, config, history, stats
│ ├── useReelComposition.js # Strip generation, payline composition
│ └── useAudio.js # Web Audio API: oscillators, noise, envelopes, SFX
├── components/
│ ├── GameConfig.vue # Collapsible settings panel with live RTP
│ ├── SlotReels.vue # 3 CSS-animated reels with win effects
│ ├── HonestGauge.vue # 1D number line with colored tier regions
│ ├── BalanceDisplay.vue # Balance + animated payout counter
│ ├── BetControls.vue # Bet input, spin, auto-spin, fast mode
│ ├── SpinHistory.vue # Recent spin log
│ ├── StatsPanel.vue # Session stats, streaks, tier hit counts
│ └── SoundToggle.vue # Mute/unmute button with localStorage persistence
└── assets/
└── style.css
Development
npm install
npm run dev
License
MIT