Inspiration
I set out to build something else: a Solana battle arcade. Simple, instantly readable games — Flappy Bird, merge puzzles — where two players stake crypto, play head-to-head, and the winner takes the pot.
Then I checked the law where I live. Real-money wagering is prohibited here, and "but it's skill-based" doesn't change that. The idea was dead before the first line of code.
What survived was the part I actually cared about: two people, the same board, one winner. So I kept the competition and changed the stake. In Foodie Drop you don't bet money — you bet crowns. Win a duel and you take two, lose and you give up one. Crowns move you through eight ranks, and your rank becomes the frame around your photo that everyone sees. The prize isn't cash. It's standing.
That constraint made the game better than the original idea would have been.
What it does
A drop-and-merge dessert puzzle: sweets fall into a glass box, identical ones fuse into the next tier, and the box fills up whether you're ready or not.
The part that doesn't exist elsewhere in this genre is Versus — real-time 1v1. Both boards run live, you watch theirs fill, you fire lightning at their tiles, and crushing them below 29% wins on the spot. Around it: 130+ levels, weekly events, friends, chat, leaderboards, and twelve languages.
How we built it
Flutter with forge2d physics, every board drawn on a fixed 430×900 canvas and scaled — so the puzzle is pixel-identical on every device. In a physics game that isn't cosmetic: a board 4% wider on your phone is a different fight.
PvP runs over a separate aiohttp WebSocket server. Physics is local on both devices, the ledger is on the server, and crowns are written only by the server at the end of a match. Monetization is RevenueCat, driving every purchase. Backend is Python + SQLite, with Google Sign-In, FCM push, and an admin console for remote difficulty tuning.
Challenges we ran into
RevenueCat and consumables. My catalog is almost all consumables, and migrating off Play Billing meant losing pendingCompletePurchase — the flag that said "charged but never delivered." RevenueCat finishes transactions itself, so that signal is gone. The obvious replacement is to read nonSubscriptionTransactions and grant anything ungranted — and that is a catastrophic bug, because that history holds every purchase forever. A player who reinstalls would receive their entire purchase history again as free currency. What shipped instead: a local ledger of granted transaction IDs plus a six-hour window. The ledger stops double-granting; the window protects me even when the ledger is empty, because the failure I'm recovering from is seconds old, not months.
Three freezes that looked identical. Players reported "the board stops responding" three times, and each time the cause was different — overlapping sockets, a snapshot quota thrashing under load, then a flag with no watchdog. Identical symptoms are not evidence of identical bugs.
A rejection that wasn't in my code. Play refused a build: "no longer supports 19,270 devices." Nothing in the repo had changed. pubspec.lock wasn't tracked, so CI re-resolved dependencies every build and a plugin patch quietly raised its own minSdk. Two builds from the same commit were not the same app.
Accomplishments that we're proud of
Shipping a finished product alone, not a prototype: a live store listing, real payments, a real backend, and twelve languages.
Real-time 1v1 in a genre that is almost entirely single-player — and making it survive dropped connections, because physics runs locally on both devices while the server holds the only ledger that counts.
Swapping the entire payment engine of a live app to RevenueCat without the store UI changing by a single line — every status string the shop reads stayed exactly the same, so nothing downstream had to be touched or retested.
What we learned
A constraint you can't argue with is worth more than a plan you love. Losing the wagering model forced me to find what was actually fun underneath it.
And in anything touching money, the dangerous bugs are silent. Nothing crashed, nothing turned red. Tests that read the source and refuse to let a number lie caught more real problems than any amount of clicking through the app.
What's next for merge puzzle game
This game is live and it stays live. What comes next is making it better, not replacing it.
iOS. The client is Flutter and the physics is platform-agnostic, so the work is store setup and RevenueCat's Apple side, not a rewrite. That doubles the audience the Versus ladder can draw from, which matters more for a game built around finding you an opponent than for a solo one.
Polish. Shipping fast left visible seams — elements sized against an older art scale, text smaller than it should be, layouts that work but weren't looked at twice. I've started that pass and it continues.
More to play. More food families, more levels, and seasons for the crown ladder so climbing means something more than once.
A better money engine. Now that RevenueCat is driving every purchase, I finally have the data to tune what I was guessing at before: which packs get bought, where players stall, which offer at which moment actually converts. Building the plumbing was step one. Reading it is step two.
Separately, on its own track, I'm going back to the staking arcade I originally set out to build — not instead of this game, but because of it. What I couldn't know from a whitepaper was whether anyone actually wants to fight a stranger over a puzzle board. Foodie Drop answered that, and it keeps answering it every day it runs.
Log in or sign up for Devpost to join the conversation.