-
-
Lost Exit — WRTeam Games
-
World map: Stars behind you. Fog ahead.
-
Shop: Skins, Coins and the Explorer's Crown.
-
Ranked on stars. Tied on time.
-
The portal card doesn't find a door. It makes one.
-
Deeper in, the maze stops being empty.
-
One card, one shot. Spend it well.
-
The maze got there first. Get back up.
-
Worth the detour.
-
No health bar, no second chance. Just timing.
-
The fastest way out, not the luckiest.
-
Sign in however you like — your progress follows.
-
Left-handed or right, loud or silent. Your call.
-
GIF
A few seconds inside the maze.
-
GIF
Behind the game: every level, tuned live.
Inspiration
We wanted to build a dungeon crawler — the anime kind, where a party works its way down through a dungeon: traps everywhere, treasure worth the risk, abilities you save for the right moment, and an exit you have to actually find.
The rest was a reaction to what's already on phones. Most mobile maze games are reflex games: something chases you, you swipe faster. We wanted the opposite. Nothing in Lost Exit is random. Goblins walk fixed patrols, every trap runs a telegraphed pattern you can watch and learn, and a death is always your mistake. Careful beats fast.
Building a game had been a dream for a long time. This is the one we finally did it with.
What it does
Lost Exit drops you into a maze you can't see. The ground opens up as you walk it, a minimap builds itself as you explore, and somewhere far from where you started there's an exit.
Between you and it: spikes, spinning axes, thunder beams, arrow launchers, and goblins on patrol. One touch ends the run. No lives to regrow, no fight you can win by mashing — the only way through is to watch a pattern until you understand it.
The hazards arrive one at a time and never all at once. The first levels are pure navigation, then spikes, then axes, then both together, then beams, then launchers. Every one runs a fixed, telegraphed cycle, and a solvability check refuses any level where two hazards can't both be dodged. The game also teaches itself exactly once: a short walkthrough on the first level, then a single card the first time you meet anything new — once per device ever, and skippable.
Every level is scored in stars. Beat the fast time for three, the slow time for two, or just get out alive for one. A single clock shows only the target still worth chasing and turns red in the last ten seconds, so you always know whether you're racing or just surviving.
A hundred levels run across four territories, with the environment changing at every border. Crossing into the next one takes 80% of the stars available so far, so stars banked early carry a weaker block later and nobody is ever permanently stuck. Fall short and you go back for stars, not for a paywall.
Chests hide in dead ends, so exploring a maze you can't see has something waiting in it besides a way to die. Early ones pay coins. Later ones drop single-use cards — shields, spells, portals — held on a wheel around the attack button. Card slots grow as you go, and each band offers one more card than you can carry, so picking one is a decision rather than a checklist. Later still, the maze starts patrolling: one goblin at first, then scouts and chiefs. You can parry one with a well-timed swing or burn it with a spell.
Signing in is meant to be invisible. On Android the game picks up your Google Play Games profile on first launch with nothing to answer, and unlocks achievements as you play — or you can stay a guest and never sign in at all. There's a global leaderboard ranked by total stars and tied on total time, and you can page all the way through it rather than staring at a top ten you'll never reach.
The whole campaign also plays with no connection at all, including on a fresh install that has never reached our server. The levels ship inside the app, an account is minted on the device, and progress reconciles once you're back online.
Sixteen products pay for it, all one-time. No subscriptions anywhere, and the Crown clears the ads for good in a single purchase.
| Tier | What it is |
|---|---|
| $1 and $3 | Character skins from a species you didn't start with |
| $5 | The three boss characters |
| $10 | Explorer's Crown, a one-time lifetime unlock |
| $0.29 to $1.79 | Four coin packs |
The core of it is two currencies that never compete. You pick a species at onboarding and get its first character free. Skins in your own species cost coins you earn by playing, and skins in the other three cost real money. For any given player and skin exactly one price exists, so nobody is ever asked to choose between grinding and paying for the same thing. Coins have a real sink as well as a shop: dying offers a revive at a price that climbs with each revive in the same attempt.
How we built it
All of it is Flutter and Dart — the game, the staff admin panel and the backend. One language across the whole stack, in a Melos monorepo of five packages, around 166,000 lines with 113 test files.
The game runs on Flame, with Riverpod for state and Hive for offline caching. The backend is Serverpod and PostgreSQL, self-hosted. The admin panel is Flutter Web.
The world is drawn rather than painted. Walls, floors and traps are generated procedurally on Canvas with no image assets at all, in isometric 2.5D, which is why a maze can be authored by a level editor instead of an artist. The characters come from the other direction: licensed pixel-art packs from CraftPix, run through Python tooling we wrote that slices and reassembles them into the sprite sheets the game needs — fifteen characters with idle, walk and attack in four facing directions. Adding a character is a script run rather than a week of drawing.
The piece that made the rest possible is a pure-Dart package holding the maze generation, shared by the game, the server and the admin panel. Mazes are seeded and built with a recursive backtracker, then braided so they aren't a single corridor, and the same package holds the difficulty curve, the star formula and the gating rules. The server builds and validates a level with the exact code the game uses to draw it, so the level builder previews a maze the way it will actually play.
Levels live on the server, not in the build. That's what makes fog of war fair without trusting the client, and it's what lets us rebalance a level after release without shipping an update. Scoring is server-authoritative for the same reason: stars are recomputed from submitted time, and a plausibility check works out the fastest a level could physically be finished and refuses anything below it.
Offline was designed in rather than bolted on. The campaign is bundled as an asset, progress is written to Hive, and everything replays through a signed outbox when the connection returns — so a player on a train keeps their stars and the server still gets to decide whether it believes them.
Purchases run through RevenueCat. Every product is fetched and bought by product id, with the store's own price string on every card and the platform's native payment sheet as the only sheet a player ever sees. Restore Purchases sits in settings, so a reinstall or a new device gets everything back. Grants arrive two ways that meet at one place in the code: a REST sync immediately after a purchase so nobody waits on a webhook, and the webhook itself for refunds and for the consumable coin packs, which credit only through the webhook and are deduplicated by transaction id.
Challenges we ran into
Going 2.5D. We started flat and it looked bad, so we rebuilt the world isometric, drawn procedurally on Canvas, with every character sprited for four facing directions. That meant redoing draw order, depth and collision so things sit in the world instead of on top of it.
The maze builder. Staff generate a maze, reroll it, and hand-place coins and hazards, and the editor has to render exactly what the game will. Two renderers that drift apart give you a level that looks right to whoever made it and plays wrong for everyone else.
A big level took 38 seconds to open. It came in as a slow loading report, but loading was never the problem — that part finished in under half a second. Level 100 has more than 1,500 separate wall segments, and each one carried its own collision box that the engine registered one at a time, re-checking the whole list after every single one. The bigger the level, the worse it got, and much faster than the level itself grew. The fix was to stop attaching a separate hitbox to every wall and make each wall be its own hitbox instead. Thirty-eight seconds became forty-six milliseconds.
Traps that were individually fair and jointly impossible. Hazards are hand-placed rather than generated, so we shipped a level with two dodgeable traps that couldn't both be dodged, and an axe that could outrun the player it was meant to threaten. Those only ever turn up by playing.
An anti-cheat that called an honest player a liar. A portal card cut a 170-cell maze down to 39 steps. The run came back at 14.7 seconds against a floor of 32, and the server refused it as impossible. The floor now accounts for every portal card a level can hand out. We found that the expensive way and fixed it in the model rather than by widening the tolerance.
Accomplishments that we're proud of
A complete, working game in about eight weeks. 278 commits between 30 July and 23 September, from an empty repo to a monetised, server-backed, multi-platform game with its own staff CMS.
The chests are our favourite part. They sit in dead ends, so exploring a maze you can't see has something waiting in it besides a way to die.
That it works offline from a fresh install, and cleans up after itself when the connection comes back.
And that all of it is Flutter.
What we learned
Full-stack Flutter was new to us. We had only ever built apps before, so writing a backend in Dart and deploying it ourselves was a first, as was standing up push notifications.
Three things we'll carry into whatever we build next. Profile before you optimise — the 38-second freeze was reported as slow loading, and loading was never the problem. Most of "offline support" isn't caching — it's identity, sessions, timeouts, ordering, and deciding what to do with a request the server is never going to accept. And ship the sink with the currency, because selling coins and giving players a reason to spend them are one feature, not two.
What's next for Lost Exit
iOS, with the same products in App Store Connect. And 100 more levels: level 101 restarts the size curve at 10×10 and climbs from there, 11×11, 12×12, the same way the first hundred did. Shorter mazes to cross, harder ones to survive. The existing 100 stay exactly as they are. Nothing in the system has a fixed length, so we can author and publish new levels without an app update.
The bigger idea is multiplayer. One large maze, everyone spawning somewhere different, all of you hunting the same exit, and able to kill each other on the way. Maze battle royale.


Log in or sign up for Devpost to join the conversation.