Modernizing a legacy platform with Docker and QEMU
In the ever-evolving landscape of technology, staying agile is paramount. However, many projects find themselves bound …

A few years ago, I wanted to show my son how magical it could be to build a game that responds to your fingers, something interactive and playful that could run right in a web browser. No app stores, no installations, just open a link and start playing. That’s how Touches was born: a simple, tactile game where circles follow your fingers and glide across the screen. The goal wasn’t just to build a game; it was to demonstrate that you can create something fun, interactive, and instantly accessible on the web, without needing a native app.
At the time I used Haxe a lot, which made OpenFL a natural choice. Haxe offered amazing performance, and OpenFL provided the tools to deploy seamlessly to the web and native platforms. It was the perfect stack for a quick, creative project that could run anywhere. Touches became a little experiment in multi-touch interaction, and it worked beautifully.
Fast forward to today: I rarely use Haxe or OpenFL. Lately I find myself building apps in Dart and Flutter, for most of the same reasons as I used to use OpenFL; syntax familiarity, good tooling, performance, and cross-platform capabilities. I also wanted to see how easy it would be to modernize Touches with the help of AI.
I’ve worked a lot with React Native over the years, and while it’s great, I’ve found that upgrading projects often becomes a nightmare. Dependency conflicts, breaking changes, abandoned native modules etc., can turn a simple update into a multi-day mission. For a project I wanted to try to avoid as much as possible of that and I had no intention of setting aside a lot of time for this experiment.
Flutter stood out for several reasons:
Stability: The framework’s backward compatibility and well-managed dependencies mean fewer surprises when upgrading.
Performance: Flutter’s compiled-to-native approach delivers smooth animations and responsive touch interactions, which are critical for a game like Touches.
Simplicity: A single codebase for web, mobile, and desktop, with a rich set of built-in widgets and tools like hot reload, makes development faster and more enjoyable.
Ecosystem: The Flutter community and package ecosystem is mature enough by now.
Beyond the technical benefits, I’ve already used it for other little projects, so maintaining Touches in Flutter means less context switching and more time for creativity.
Before diving into code, I used Le Chat Pro to plan the migration. I asked to analyze the project and make sure there would be no surprises, unsupported features or other pitfalls where perhaps OpenFL would differ from Flutter. This step saved me hours of trial and error and gave me a clear roadmap for the rewrite.
For the actual development, I used Claude Code. The AI handled the heavy lifting of syntax translation and even suggested optimizations for touch interactions and animations based on what was more performant in Flutter. The rendering works a bit differently there.
Claude Code helped translate OpenFL’s touch logic into Flutter’s GestureDetector and Listener widgets.
The syntax was different, but the core behavior tracking multiple touches, detecting pressure, and rendering circles transferred well. Pressure sensitivity is unfortunately currently not available on the web platform so that it native only.
One of the biggest challenges was recreating the original game’s animations. In OpenFL, I had separate controllers for fading and movement, allowing for independent timing and effects. However, on Flutter for the web, multiple AnimationController instances caused noticeable jank, even on powerful devices like a recent iPhone 16 Pro.
The Solution: I consolidated the animations into a single AnimationController for both fade and movement. This meant shared timing, but it aligned with how the game originally worked and eliminated performance issues. As I understood it that cut the object redraw times in half.
The migration to Flutter didn’t just replicate the original game - it supercharged it. After letting my daughter and her friends test the game they suggested a few new features and thanks to Flutter and Claude those turned out really easy to implement:
Physics Mode: Gravity and Collisions In Physics Mode, circles now respond to gravity and bounce realistically off both the screen edges and fixed objects placed by the player. Using the flame game engine, I implemented gravity and collision detection. Players can draw static objects onto the screen, creating obstacles that circles interact with dynamically.
Animation Length: Slower fades Allows setting the lenght of animations and therefor making the circles / brush strokes stay on screen longer.
Other animation modes: Big bang and Vapor THe original game only had attraction mode, i.e. circles would travel between your fingers in multi touch or follow your finger in one touch. Now there’s more modes that creates other interesting effects with the circles looking like they’re evaporatiing och exploding outwards.
At this point AI isn’t a magic wand: It accelerated development but in this case couldn’t solve certain issues, such as performance issues. I think I probably could have come up with a solution myself if I would have spent more time on it; but maybe not. There are definitely render limitations on the web platform, it’s just a fact at this point.
Flutter web has limits: For animation - heavy games, test performance early and budget for optimizations. Trade offs are okay: Touches still runs smoothly for its core interactions - sometimes “good enough” is the right balance for a passion project.
Rewriting can be creative: This project became more than a port, it was a chance to reimagine Touches. Flutter’s flexibility and AI tools made it easy to prototype and refine new features.
Touches is now live as a Flutter PWA at https://touches-game.excello.digital. Give it a try on your phone and see how the new physics and drawing modes feel!
Have an idea for a fun new feature? I’d love to hear it! Whether it’s a new interaction, a creative mode, or a technical tweak, get in touch!
In the ever-evolving landscape of technology, staying agile is paramount. However, many projects find themselves bound …
Sending emails used to be a simple mechanism but as it became more and more abused and harder to discern legit emails …
Our team of experts is ready to help you with your infrastructure challenges. We’ll give you honest and personal treatment. Get in touch to learn more.
Get in touch!