Inspiration

We were captivated by the Reddit Daily Games hackathon theme: community-designed daily content. The vision was clear—what if Reddit's community could collectively design new dungeons every single day, and players would experience a fresh challenge each time they logged in? This creates a virtuous cycle: players discover new layouts daily, the community competes for votes to see their dungeon featured, and the game stays endlessly fresh.

We drew inspiration from classic dungeon crawlers (Binding of Isaac, Enter the Gungeon) but wanted to make it Reddit-native and community-driven. The result: Snoo's Ever-Shifting Dungeon—a real-time action RPG where the Reddit community is the game designer.

What it does

Snoo's Dungeon is a real-time dungeon crawler where:

  • Players choose from 3 unique classes (Warrior, Rogue, Dark Knight) with distinct playstyles and passive abilities
  • Combat involves WASD movement, Space to attack, Q for ranged arrows, Shift to dash, and E for class-specific area abilities
  • Waves of enemies escalate in difficulty across 9 waves, culminating in epic 2-phase boss encounters
  • Daily dungeons are either community-submitted (if validated and upvoted) or fall back to our curated rotation of 30 hand-crafted maps
  • Leaderboards let players compete globally, with ghost markers showing where other players died
  • Equipment & achievements add progression and replayability
  • Cross-platform with desktop keyboard controls and mobile touch joystick + button grid

The core innovation: the Reddit community designs the dungeons. Anyone can submit a dungeon layout, upvote favorites, and if a submission gets ≥5 upvotes and passes validation, it becomes tomorrow's daily dungeon.

How we built it

Architecture

We built Snoo's Dungeon as a React + Phaser 3 frontend with an Express.js backend on Reddit's Devvit platform, leveraging Redis for persistence:

Frontend (React + Phaser 3)

  • React 19 component tree for UI (class selection, leaderboard, admin panel)
  • Phaser 3.90.0 game engine running a GameScene with full game logic
  • Vite 6 for fast HMR development and optimized production builds
  • Tailwind CSS for responsive UI styling
  • Howler.js for cross-browser sound (OGG + MP3 fallbacks for Safari)

Backend (Express.js + Devvit)

  • 9 API endpoints: /api/daily-dungeon, /api/submit-score, /api/leaderboard, /api/ghosts, /api/streak, and admin endpoints
  • Map validation system using BFS flood-fill algorithm to reject troll submissions:
    • Checks 80% connectivity (largest floor component ≥80% of total)
    • Detects boss arenas (5×5, 4×4, or 3×3 open spaces)
    • Validates teleport pairs (max 4 tiles each)
    • Enforces tile count (20-80 floor tiles)
  • Hybrid voting system: Checks community submissions → if valid + ≥5 upvotes, uses it; else falls back to curated queue
  • Reachability system: Client-side BFS ensures all enemy/boss/loot spawns on tiles player can actually reach
  • Redis for scores, leaderboards, daily dungeon source, and ghost positions (7-day TTL)

Game Logic (4150+ lines of TypeScript)

  • 3 balanced character classes:
    • Warrior: 220 HP, 22 dmg, wide cleave (hits 3 enemies), 3% heal/attack + 8% on-kill
    • Rogue: 110 HP, 16 dmg×2, 25% dodge chance, 6% heal on-kill, teleport ability
    • Dark Knight: 150 HP, 22 dmg, fire burn (8 dmg/tick × 3s), 8% lifesteal on-kill
  • 3 regular enemies (Orc, Skeleton, Vampire) + 3 bosses (Pink Monster, Owlet, Dude) with 2-phase mechanics
  • Wave scaling: 10% difficulty per wave, capped at 2.0× damage
  • Equipment system (9 items, 3 tiers) with stat bonuses
  • 30+ achievements for progression
  • Mobile controls: relocating joystick (60px radius, 12px dead zone), 2×2 button grid, cooldown arc overlays, multi-touch support
  • Desktop controls: WASD/arrows, Space/Q/Shift/E, auto-attack toggle

Data Flow

  1. Player loads game → fetches /api/daily-dungeon → receives community or curated map layout
  2. Player plays → attacks enemies, collects loot, reaches boss
  3. Game over → submits score to /api/submit-score → checks leaderboard via /api/leaderboard
  4. Next day → server runs scheduler → validates top community submission → uses it or falls back to curated map

Asset Pipeline

  • Sprites: Tiny RPG + Sprout Lands asset packs (40 total images, heavily optimized)
  • Sound: 10 SFX (attack, hit, kill, dash, wave, boss, gameOver, victory, pickup, healing) in OGG + MP3 formats
  • Maps: 10 hand-designed base layouts + 20 variations (mirror/rotate transforms) = 30 daily options

Challenges we ran into

1. Map Validation (Preventing Troll Submissions)

Problem: Without validation, players could submit unwinnable maps (all walls, scattered pixels, or disconnected arenas).

Solution: Implemented BFS flood-fill algorithm that:

  • Finds largest connected component of floor tiles
  • Rejects if <80% connectivity (fragmented maps)
  • Detects boss arenas to ensure they're accessible
  • Validates teleport pairs
  • Rejects maps outside 20-80 tile range

This prevents game-breaking submissions while allowing creative community designs.

2. Reachability System (Spawns in Unreachable Areas)

Problem: Enemies/bosses spawned in tiles player couldn't reach → unwinnable games.

Solution: Client-side reachability computation:

  • Run BFS from player spawn at game start
  • Build reachableFloorTiles[] set
  • All enemy/boss/loot spawns snap to nearest reachable tile
  • Eliminates dead zones while preserving map creativity

3. Class Balance (3 Iterations)

Problem: Rogue was overpowered (164 DPS vs Warrior 47 DPS), trivializing bosses.

Iteration 1: Buffed Warrior/DK → Rogue still too strong Iteration 2: Cut Rogue HP to 75 → instant death, unplayable Iteration 3: Rogue 110 HP + 25% dodge + 6% heal on-kill → finally balanced

Final DPS: Warrior 47 → 66 (after cleave), Rogue 108, Dark Knight 66 (+ burn damage). Classes now have distinct niches.

4. Mobile Controls (Multi-Touch Complexity)

Problem: Players couldn't move AND attack simultaneously on mobile; button overlap made controls unresponsive.

Solution: Complete overhaul:

  • Relocating joystick (left half, 60px radius, 12px dead zone) for movement
  • 2×2 button grid (right half) with 1.2× hit zones for forgiveness
  • Multi-touch config: 3 active pointers (joystick + 2 buttons)
  • Continuous hold attack: hold button = auto-fire at attack rate
  • Cooldown arcs: real-time pie-chart overlays on buttons
  • Visual feedback: scale on tap, glow stroke on press

Result: Fluid multi-touch gameplay even on small screens.

5. Boss HP Progression

Problem: Owlet (Wave 6) had 400 HP while Pink Monster (Wave 3) had 500 HP—progression broken.

Solution: Recalibrated boss HP scaling:

  • Pink Monster: 600 HP
  • Owlet: 700 HP
  • Dude: 800 HP

Ensures bosses felt progressively harder, not easier.

6. Wave Scaling Too Aggressive

Problem: 15% per wave + 2.5× damage cap = 235% stats by Wave 10, impossible to survive.

Solution: Reduced to 10% per wave + 2.0× damage cap. More sustainable while still challenging.

7. Cross-Browser Sound (Safari MP3 Support)

Problem: OGG files didn't play on Safari; Howler.js fallback wasn't working.

Solution: Generated MP3 fallbacks for all 10 SFX via ffmpeg. Howler.js now tries OGG first, falls back to MP3 on unsupported browsers.

Accomplishments we're proud of

Community-Driven Content Loop: First dungeon crawler where Reddit designs the dungeons. Voting system incentivizes creative submissions.

Flawless Balance: 3 classes with unique playstyles, all viable. 60+ hours of playtesting and iteration.

Boss System: 3 unique bosses with 2-phase mechanics, cinematic entrances, and devastating abilities. Each feels epic.

Mobile Parity: Desktop AND mobile with identical gameplay. Multi-touch support that actually works.

Validation System: BFS algorithm prevents troll submissions without stifling creativity.

60 FPS Performance: Smooth gameplay even with 8+ sprites, particles, and sound effects.

Reachability System: Players never spawn in unwinnable situations.

Asset Optimization: Reduced from 130 sprites to 40, load time under 3 seconds.

Sound Design: Retro-style SFX with cross-browser fallbacks.

Leaderboard + Ghosts: Social features that encourage competition and discovery.

What we learned

  1. BFS flood-fill is surprisingly powerful for procedural validation. Simple algorithm, elegant solution.

  2. Class balance requires DPS math, not gut feel. We calculated exact damage per second to fix Rogue.

  3. Multi-touch is hard. Phaser's activePointers config and pointerId tracking are essential. Generous hit zones (1.2×) matter more than precision.

  4. Asset optimization wins: Reducing sprites from 130 to 40 cut load time by 2+ seconds.

  5. Community voting is a feature, not a bug. Letting players design dungeons makes them invested in the game's success.

  6. Fallback systems matter: Curated maps ensure the game is always playable, while voting system gives community a voice.

  7. Sound design sells polish: Subtle SFX on every action (attack, dash, kill) makes the game feel responsive and tactile.

What's next for Snoo-s-Dungeon

  • Seasonal Leaderboards: Monthly/yearly rankings with cosmetic rewards
  • Co-op Dungeons: 2-4 player cooperative mode (stretch: PvP arenas)
  • Cosmetic Skins: Unlockable character skins via achievements
  • Map Editor UI: In-game dungeon designer so players don't need external tools
  • Advanced Abilities: New class passives unlocked via progression
  • Difficulty Tiers: Hard mode with modifiers (curse effects, limited HP heals, enemy buffs)
  • Streamer Integration: Twitch chat votes on next class/dungeon

Built with

Category Technologies
Frontend React 19, TypeScript, Phaser 3.90.0, Tailwind CSS, Vite 6
Backend Express.js, Node.js, Reddit Devvit API
Database Redis (Devvit @devvit/redis)
Audio Howler.js 2.2.4, OGG/MP3 formats
Build Tools Vite 6, ESLint, TypeScript compiler
Hosting Reddit Devvit platform (React Native web)
Algorithms BFS flood-fill, Phaser physics engine, multi-touch event handling

Built With

  • bfs-flood-fill
  • eslint
  • express.js
  • howler.js-2.2.4
  • multi-touch-event-handling
  • node.js
  • ogg/mp3-formats
  • phaser-3.90.0
  • phaser-physics-engine
  • react-19
  • reddit-devvit-api
  • reddit-devvit-platform-(react-native-web)
  • redis-(devvit-@devvit/redis)
  • tailwind-css
  • typescript
  • typescript-compiler
  • vite-6
Share this project:

Updates