The 16ms Problem Belongs to Everyone
Games and Flutter apps share more than a frame budget โ they share a definition of "feel."
The first time I read the phrase "game feel," I thought it was nonsense. Feel? Games are code. Things happen or they don't. Either the bullet hits or it doesn't.
Then I spent three years building Flutter apps in fintech, and I realized I'd been working on game feel the whole time. I just didn't have the word for it.
The 16ms problem
In Flutter, you have 16 milliseconds to render a frame. Miss that window and the user feels it โ not as "lag," but as something off. A button press that feels mushy. A scroll that feels heavy. They can't tell you what's wrong, but they know.
Games have the exact same budget. The exact same problem. Hit 60fps or the player's hands stop trusting the controller.
What surprised me, coming from fintech, is how much of my day-to-day was already about this. We'd spend a week optimizing a transaction list because the scroll stuttered on mid-range Androids. We'd argue for hours about whether a confirmation dialog should fade in over 200ms or 250ms. Nobody called it game feel. We called it "polish." Same thing.
Curves are everything
Here's the lesson Flutter beat into me: linear animations are almost always wrong.
A button that scales from 1.0 to 0.95 on press, linearly, feels mechanical. Apply Curves.easeOutBack and suddenly it feels alive โ like the button has a tiny bit of weight, a tiny bit of personality. Same animation. Same duration. Different curve. Completely different feel.
Game developers have known this forever. They call it "juice." But in Flutter I learned to feel it before I learned the vocabulary:
- easeOut for things the user initiated (taps, swipes) โ fast start, soft landing
- easeIn for things appearing on their own (notifications, modals) โ gentle build, decisive finish
- easeInOut for transitions between two states the user is watching
- elasticOut for moments that deserve celebration โ but only sparingly, or it gets exhausting
When I started prototyping games, I expected to learn animation from scratch. Instead I found myself using the same vocabulary, just with different tools.
Frame budgets train your eyes
In fintech we cared about performance because users on $80 Android phones still need to send money home. That meant constant profiling โ pulling up the Flutter DevTools timeline, looking for the red bars, hunting down the widget that was rebuilding 300 times per second for no reason.
That habit transfers directly to games. The difference is just what you're profiling. Instead of "why is this ListView rebuilding," it's "why is this particle system allocating." Same brain, same patience, same satisfaction when the timeline goes green.
What I had to unlearn
Not everything translates. Flutter rewards declarative thinking โ describe what the UI should look like, let the framework figure out the diff. Games punish that. In a game loop, you're imperatively pushing state forward 60 times a second, and pretending otherwise leads to bad performance and worse code.
I also had to unlearn the fintech instinct of preventing things. In banking apps, every interaction is a potential mistake to guard against. In games, every interaction is an invitation to play. The button doesn't ask "are you sure?" โ it goes thwack and gives you a particle burst.
That shift in posture, from defensive to generous, has been the hardest part. And the most fun.
The bridge
If you're a mobile dev thinking about games, here's the thing nobody told me: you're closer than you think. The fundamentals you use every day โ animation curves, frame budgets, state, gesture handling, responsive layouts โ are the same fundamentals games rely on. You're not starting from zero. You're starting from a side you already know.
The work now is learning what the other side knows. Game loops. ECS. Shaders. Level design. Juice as an explicit craft, not an accident of polish.
I'm a year into that learning. Most of it still feels foreign. But every now and then I'll be tuning an animation curve in Flame and catch myself thinking โ oh, this is just the transaction list, but with enemies.