🍓 TileMatch UGC — Remixing Match-3 with Fruit Ninja energy

One-liner

A simple, joyful tile-matching game where players can design and share wild UGC levels — imagine match-3 mechanics meets Fruit Ninja flair: fruity visuals, combo sparks, and editor-made levels nobody’s seen before.


Inspiration

I’ve always loved puzzle games, but traditional tile-matching titles eventually feel stale—levels are fixed, content dries up, and players move on. I wanted to break that mold. What if players could create their own puzzles and share them with the world, just like building custom maps in other genres? That spark became TileMatch UGC. Devvit 0.12 made prototyping fast, so I leaned into that: fast dev cycles, fast feedback, fast sharing.

The new twist: add fruit elements and a dash of Fruit Ninja vibes — satisfying swipe/clear effects and flashy combos — while keeping the core match-3 easy and approachable.


What I built

  • Core gameplay: classic match-3 + fruit elements (special tiles, streaks) with quick, satisfying feedback (particles, sounds).
  • UGC editor: drag-drop tile palette, layer support, and a one-click “test level” flow: design → test → publish.
  • Light publishing flow: save level JSON, publish to subreddit or in-app browser, and let players browse and play community levels.
  • Solvability tester: a pre-test step that runs a solver to indicate if a custom level is solvable before publishing.
  • Leaderboard: per-level scoring with tie-break rules and simple anti-abuse heuristics.

Stack: React + TypeScript, custom game logic hooks, small serverless endpoints (for saving levels, leaderboards), Devvit for Reddit integration.


What I learned

One fun part of this project was diving into pixel art creation. Instead of grabbing existing assets, I taught myself to draw fruit tiles and effects with Aseprite . Exporting them as sprite sheets gave me compact, efficient assets that load fast and feel authentic to the retro puzzle style. This added personality to the game and made it more fun to play and design for. A big design challenge in user-generated puzzle games is solvability. I realized I had to prevent frustration for creators and players.

So I built a solver/validator that runs before a level can be published. It mathematically checks whether the layout can be solved within the rules (tile click → added to slot, max 7 slots). If not, the editor warns the user and blocks publishing. This ensures that every shared level is beatable, while still letting creators push difficulty.

Another lesson came from performance testing. Rendering hundreds or thousands of tiles in a custom level can bog down the UI, especially inside the Devvit sandbox. Two options emerged:

Canvas + JS: great for batching rendering, but can struggle with very large tile sets if not optimized. Devvit native UI components: safer inside the sandbox, but less flexible for animations and particle effects.

I ended up balancing both approaches — using Canvas where raw rendering speed matters (tile grid, animations) and React components for menus, modals, and editor logic. This hybrid lets the game scale while staying smooth.

Challenges & concrete solutions

1) Devvit upload size & sandbox restrictions

Problem: asset size limits, restricted runtime / filesystem, and sandboxed environment for uploads/deploys.

Solutions

  • Keep level format tiny: JSON that references small sprites by key. Don’t upload big images inside the level object.
  • Use CDN / external blob storage for larger assets (spritesheets, audio). On publish, upload only metadata + CDN URLs.
  • Sprite packing: combine many small icons into a single spritesheet and load selectively (reduce HTTP overhead).
  • Client-side processing: do heavy work (tile rendering, solvability test) in the browser when possible; server only persists state.
  • Chunk and gzip: compress level JSON before sending; tooling to detect duplicates to avoid reuploading unchanged assets.
  • Fallback: store drafts locally (IndexedDB) and push only metadata to Devvit to comply with sandbox.

2) Leaderboard: sorting, fairness, and abuse prevention

Problem: How to sort scores fairly across random tiles / UGC levels and avoid replay-exploit or manipulated timestamps?

Design & Implementation

  • Per-level leaderboards (each levelId has its own sorted list).
  • Primary sort = score (desc). Secondary sort = completion time (asc). Tertiary = earliest submission timestamp (asc). This rewards higher score, then speed, then who first achieved it.
  • Score canonicalization: compute canonical scoring on the client but send proof (compact replay hash or seed + actions). Server replays the important events deterministically where feasible.
  • Seeded randomness: when a level is played, generate a seeded RNG (levelId + playAttemptId) and store that seed with the score so results are reproducible.
  • Rate limits / anti-cheat:

    • Throttle submissions per user per minute.
    • Validate scores server-side with basic checks (impossible scores, absurdly low play times).
    • Optionally require proof-of-play: minimal replay log (moves or RNG seed + move counts) that server can partially verify.
  • UI: show "Verified" badge if server validated the replay; otherwise label as "Unverified".


  • For creator-placed boards: run isLevelSolvable(layout) before allowing publish. If unsolvable, show actionable hints.
  • For generated boards: generate candidate boards and run quick solvability tests until you get an N tries success (cap tries to keep cost low).
    • Randomness controls: allow designers to set a difficulty parameter; higher difficulty means fewer guaranteed initial matches or lower immediate combos.
    • Replay determinism: store the seed with submitted scores so leaderboard validation can replay the session deterministically.

To be done

  1. MVP: editor + test + publish (local), per-level leaderboards, solvability check.
  2. Add CDN for assets, Devvit integration for posting.
  3. Seeded randomness + verified leaderboards.
  4. Social features: follow creators, favorite levels, remixes.

5. Tournaments: theme packs (e.g., “Fruit Frenzy week”).

In summary, TileMatch UGC is a tiny, addictive match-3 with a big twist: the community builds the content.

Built With

Share this project:

Updates