4.5 KiB
4.5 KiB
Virtue Slots
A browser-based slot machine game with a Christian religious theme, built with Phaser 3 and vanilla JavaScript. May Fortune Favor the Faithful.
Features
- 10 holy symbols — from Dove to Holy Grail, each with unique payout values scaled by holiness
- Animated reels — smooth spin, decelerate, and snap-to-symbol with sprite overlays
- Win sequence — "MATCH: 3×" banner punches in with elastic animation, sparkles, and shaking; followed by arcing coin animations splitting 60% to the player and 40% to The Lord
- Loss sequence — a devil carries the spent money up to the Sin box with a wobble animation
- Split labels — on a win, animated callouts show "YOUR WINNINGS 60%" and "THE LORD'S TITHE 40%" so the player always understands where the money goes
- The Reckoning — two filling vials on the right track cumulative funds for "The Lord" and "Sin"; whichever reaches $2,000 first wins; vials shake progressively harder as they approach the limit
- Living background — stars drift, twinkle, and pulse independently for an ambient celestial feel
Tech Stack
| Thing | Choice |
|---|---|
| Game engine | Phaser 3 via CDN |
| Language | Vanilla JavaScript — ES6 modules |
| Bundler | None — files are served directly |
| Canvas | 1600 × 900, FIT + CENTER scale mode |
Running Locally
Browsers block ES6 module imports from file://, so serve over HTTP:
# Python (built-in)
python3 -m http.server 8080
# Node (npx)
npx serve .
Then open http://localhost:8080 in any modern browser.
Controls
| Action | Input |
|---|---|
| Spin | Click the SPIN button |
| Spin | Press Space Bar |
Game Economy
| Setting | Value |
|---|---|
| Starting funds | $1,000 |
| Cost per spin | $50 |
| Win rate | ~1 in 15 spins |
| Win split | 60% to player · 40% to The Lord |
| Loss result | $50 added to the Sin total |
Symbols & Payouts
Symbols are ordered by holiness. A three-of-a-kind match pays the symbol's full payout value.
| Symbol | Holiness | Payout |
|---|---|---|
| Dove | 1 | $200 |
| Joel Osteen | 2 | $300 |
| Holy Bible | 3 | $400 |
| Lamb of God | 4 | $500 |
| Crown of Thorns | 5 | $600 |
| Halo | 6 | $700 |
| The Cross | 7 | $900 |
| Jesus on Cross | 8 | $1,100 |
| Baby Jesus | 9 | $1,300 |
| Holy Grail | 10 | $1,500 |
Project Structure
index.html Loads Phaser 3 (CDN) and main.js as type="module"
main.js Phaser.Game config — registers all three scenes
state/
GameState.js Singleton: playerFunds, lordFunds, sinTotal, spinning flag
utils/
RNG.js shouldWin() (~1/15), pickResults() for reel targets
objects/
Symbol.js SYMBOLS array — id, label, holiness, payout, color
Reel.js Single reel: virtual infinite strip, pooled cells, sprite overlay
SlotMachine.js Orchestrates 3 reels; manages spin timing and result callback
WinAnimation.js Match banner → gold flash → arcing coin animation → split labels
LossAnimation.js Devil graphic rises to the Sin box
MatchBanner.js Full-screen "MATCH: 3× {label}" overlay with particle burst
VialDisplay.js Filling vial with shake escalation and winner detection
scenes/
BootScene.js Preloads assets (symbol spritesheet), then starts game
GameScene.js Background, stars, slot machine, vials, input handling
UIScene.js Overlay HUD: fund boxes (top), message + SPIN button (bottom)
assets/
symbol_sprites.png 200×100 px spritesheet — 10 frames, one per symbol in order
Scene Communication
Scenes communicate exclusively through the global Phaser event bus (this.game.events):
| Emitter | Event | Payload |
|---|---|---|
| UIScene | spin |
— |
| GameScene | win |
{ playerGain, lordGain, symbol } |
| GameScene | loss |
{ sinAdded } |
| GameScene | funds-updated |
— |
| GameScene | spin-complete |
— |
| GameScene | insufficient-funds |
— |
| VialDisplay | vial-winner |
{ winner } |
Sprite Sheet
assets/symbol_sprites.png must be a horizontal sprite sheet:
- Frame size: 200 × 100 px
- Frame count: 10 (one per symbol)
- Frame order: must match the
SYMBOLSarray order inobjects/Symbol.js(Dove at index 0, Holy Grail at index 9)
License
Do whatever you want with it. Probably don't build a real gambling site.