Back to Writings
Harbor™ • Engineering

Sailing in the Sandbox: Building a Custom Water Physics Engine in Flutter and Flame

May 28, 2026

Driving a car is simple: turn the wheel, and the tires immediately grip the asphalt, changing your direction. Stopping is as easy as applying friction directly to the wheels. Boats are entirely different. They operate in a fluid medium with zero direct friction. Turn the wheel, and the rudder acts against water resistance, slowly sliding the stern out. Pull back the throttle, and the vessel continues coasting forward on momentum for hundreds of feet.

Boating safety courses are excellent at teaching you rules and marker colors, but they are significantly less helpful when you are trying to dock in a tight slip with a strong crosswind. To help boaters master these scenarios, we built **Harbor**—a 2D, top-down physics simulator built entirely in Flutter using the **Flame** game engine.

But simulating water-based physics accurately on a mobile device required us to throw away standard rigid-body physics engines like Box2D and build our own custom hydrodynamics solver.

Why Box2D Fails on Water

Popular physics engines like Box2D are designed for solid objects colliding on dry land. They are optimized for rigid contact solver equations and basic gravity vectors. While you can tweak parameters like linear and angular damping, they cannot model the directional, fluid forces that dictate how a boat moves:

- **Directional Drag (Anisotropic Friction):** A boat's hull is shaped to slip forward through water with minimal drag, but it presents massive resistance when pushed sideways. A simple damping coefficient slows down an object equally in all directions, failing to capture the classic "slide" of a turning boat.

- **Propeller Thrust and Rudder Deflection:** Steering force in a boat is not applied at the center of gravity; it is generated by pushing a stream of water across a angled rudder at the stern, producing both rotational torque and forward thrust simultaneously.

Modeling Fluid Dynamics in Dart

To capture the authentic feel of boat handling, we developed a dedicated hydrodynamic solver in Dart, executing on Flame's update ticks:

First, we decompose the boat's velocity vector into two components relative to its hull orientation: **forward velocity** and **lateral velocity**. We then compute drag forces independently:

- *Forward Drag* is modeled as quadratic ($F_{df} = -c_f \cdot v_f \cdot |v_f|$), keeping resistance low at slow docking speeds but ramping up exponentially at planing speeds.

- *Lateral Drag* is set significantly higher ($F_{dl} = -c_l \cdot v_l \cdot |v_l|$), resisting sideways movement but allowing the stern to "drift" out realistically under heavy rotation.

Next, we calculate **Wind Drift** (Leeway). Every boat has a distinct profile above the waterline that acts as a sail. Our engine applies a continuous wind vector to the boat's center of lateral resistance, creating realistic drift dynamics that force players to actively correct their heading when docking in a breeze.

The Sandbox Classroom

By simulating directional drag, wind drift, propeller torque, and momentum in real-time, Harbor creates an interactive, consequence-free playground. You can crash into pilings, miscalculate current vectors, and drift past your slip as many times as it takes to build physical intuition. Mastering the water doesn't require a real boat—just a accurate sandbox.

Master the Helm

Harbor™ is currently in development, powered by our custom hydrodynamics engine built in Flutter and Flame.

Learn More about Harbor