DEV BLOG
Build logs, breakdowns, and lessons learned from shipping browser games, flight sims, and interactive web apps.
Why Every Gravity Simulator Needs a Softening Parameter
Newton's law divides by distance squared, and distance can be zero. Without one small fudge in the denominator, two bodies that drift too close will be flung to infinity at a speed your simulation can never recover from.
How I Handle Input on Both Touch and Desktop
I budgeted a weekend to build an input abstraction layer for Oliver's Racers and never wrote one. Five plain fields on the car and a single addition turned out to be enough, for a reason that is arithmetic rather than clever.
The Three-Body Problem, Explained by Watching Mine Fail
Two objects orbiting each other is solved maths. Add a third and prediction becomes impossible. Not hard, impossible. I built a figure-eight preset to show off the famous stable solution, and it doesn't work, which turns out to demonstrate the point rather better.
Godot Web Export Size: 37 MB of Engine, 0.7 MB of Game
If your Godot HTML5 export is too big, measure it before you optimise it. In my shipped racing game the engine .wasm is 37.68 MB and the whole game .pck is 0.70 MB. And my CDN was serving every uncompressed byte of the big one.
Euler Integration Ruins Orbits. Swapping Two Lines Fixes It.
If your planets slowly spiral outward and drift off screen, your physics probably isn't wrong. Your integrator is. The difference between an orbit that decays and one that holds is the order of two lines of code.
WebGL Context Lost on iOS Safari: How to Recover Instead of Reloading
iOS Safari drops the WebGL context on memory-heavy pages, and Godot can't rebuild one. So the default is a dead 'please reload the page' message. Here's the webglcontextlost handler that recovers automatically, and how to force the failure in a test with WEBGL_lose_context.
What Is an N-Body Simulation? A Guide From Someone Who Built One
An n-body simulation works out how a group of objects pull on each other under gravity, one small step at a time. Two bodies can be solved with a pencil. Three cannot, and that's not a limitation of computers. It's a fact about the universe.
GLB Not Loading in three.js? Draco's Decoder Is Probably Why
Every glTF guide points you at Draco because it compresses hardest. But drei's useGLTF bundles the meshopt decoder and fetches Draco's from a CDN at runtime. So a Draco-compressed GLB can fail with a confusing error about 'extensions' that has nothing to do with your model.
How to Simulate Gravity in JavaScript (In About 40 Lines)
Newtonian gravity in a browser is genuinely small. A nested loop, one equation, and two lines that update velocity and position. Here's the actual code from my n-body sandbox, including the bit I got wrong.
A Lock on the Save File (and Why It's Only a Lock)
The save file was plain text. You could open it in Notepad and set your money to a million. Fine for a while. Until some of that content became premium.
The Day My Game Was Just Blue
Someone changed the map in Oliver's Racers and the whole world disappeared. The HUD still worked. The minimap still worked. Just the actual game was gone.
A Classic Kart Racer Taught Me to Let Players Wait
My first version of power-ups fired the second you touched them. It worked immediately, which should have tipped me off that it was boring.
What I Learned Shipping 14 Projects in One Year
14 games, apps, and sites shipped in one year. An honest retrospective on scope, perfectionism, reusable backends, and what each project taught the next.
Static Export With Next.js: Shipping a Portfolio That Loads Instantly
output: 'export' in next.config.ts builds to a plain folder of HTML/CSS/JS. No Node server needed. Deploy to S3 + CloudFront. Here's how the portfolio achieves sub-second loads.
Why I Chose Godot Over Unity for a Web Flight Sim
Godot 4.7 with GL Compatibility exports to WebGL2 with no special server headers, runs on phone browsers as a PWA, and ships a tiny binary. Here's why it won over Unity.
My WebSocket Architecture: One Backend for All Games
A single AWS WebSocket API serves every multiplayer game on the site. The backend is game-agnostic. It just relays JSON between room members. Here's how that works.
N-Body Gravity Simulation at 60fps in the Browser
Every pair of bodies pulls on every other. That's O(n²) force calculations per frame. Here's how the cosmic gravity sandbox keeps it smooth at 60fps with Canvas 2D, Verlet integration, and careful timestep choices.
Zero External Assets: Generating All Art from Code
Every mesh in Oliver's Planes and Oliver's Racers is built from Godot primitives. Boxes, cylinders, cones. No Blender, no texture files, no downloaded assets. Here's why and how.
Why I Build Everything in the Browser
No installs, no app store gatekeepers, instant access via URL. The browser is the most universal platform on Earth. And it's more capable than most people think.
Arcade Flight Physics: Lift, Drag, and Keeping It Fun
The flight model behind Oliver's Planes: speed-dependent lift, quadratic drag, momentum grip, ground-proximity assists, and a minimum throttle floor that keeps beginners in the air.
The Pose System: Blending In With Your Environment
Painting yourself the right color is only half the battle. The pose system lets you morph your chameleon's silhouette to match rocks, boxes, or flat surfaces.
The AWS Backend: Lambda, DynamoDB, and API Gateway for Games
One serverless backend powers multiplayer for Garden Gnomes, my hide-and-seek game, and Oliver's Racers. Here's the full architecture. API Gateway WebSocket, Lambda, and DynamoDB.
Online Hide and Seek: Syncing Game State Over WebSockets
How do you sync paint colors, positions, poses, and a game clock over WebSockets with no game server? Host-authoritative design, throttled updates, and a lot of accumulators.
Building an AI Seeker That Feels Fair
The practice mode AI seeker needs to be challenging but beatable. Here's how suspicion, patrol routes, line-of-sight, and movement detection combine into something that feels alive.
Building Preset Solar Systems: Figure-Eight Orbits and Galaxy Collisions
Curated presets make the Cosmic Gravity Sandbox instantly impressive. Here's how I set up a stable figure-eight three-body orbit, and a galaxy collision.
How the Lap Leaderboard and Champion Car System Works
How the live room leaderboard ranks every racer by best lap, how earning Champion Gold works, and how GameState persists money, cars, and records to a ConfigFile.
Color Sampling: How the Chameleon Steals Surface Colors
The core mechanic of the game is stealing colors from walls and floors. Here's the raycast-based sampling system, the swatch palette, and how paint state syncs over the network.
Drawing Orbital Trails That Don't Kill Performance
Thousands of trail points per frame will destroy your Canvas 2D framerate. Here's how I got glowing orbital trails running smoothly in the Cosmic Gravity Sandbox.
Building a 3D Hide-and-Seek Game from Scratch
I loved the hide-and-seek genre so much I built my own version in Godot 4.7. With online multiplayer, 5 stages, and a full 3D world.
The Nitro Boost System: Game Feel Through Juice
How a two-second meter, a drift-refill reward loop, and the right particle effects turn a simple speed buff into the most satisfying button in the game.
The Quest System: Giving Players Reasons to Keep Flying
Without goals, a flight sim is a screensaver. Here's how I built a lightweight quest system that gives players progression without drowning them in menus.
Making a PWA From a Godot Game: Play on Your Phone Like an App
Godot can export to the web, but the result isn't installable out of the box. Here's how I turned a ~39MB .wasm flight sim into a proper PWA with offline support and home-screen icons.
Touch Controls That Don't Suck: Designing for Phone and Desktop
How I built a single virtual joystick that handles steering, gas, and braking. Plus why you MUST disable emulate_mouse_from_touch in Godot's project settings.
Mouse Steering in a Flight Sim: The UX Problem Nobody Talks About
Flight sims assume you own a joystick. Most people don't. Here's how I made mouse steering feel natural. Hold to steer, release to auto-level, with smoothing that hides the jank.
Procedural Worlds: 10 Biomes From One Terrain Algorithm
One terrain algorithm, 10 completely different worlds. From Green Valley to Neon Night City to Luna Rally. Here's how a Dictionary of parameters does all the heavy lifting.
Building 5 Flyable Planes from Code: No 3D Models Needed
Every aircraft in Oliver's Planes is built from Godot primitives. Boxes, spheres, and cones. No Blender, no FBX files, no UV maps. Here's how each airframe is assembled in pure GDScript.
Building a Minimap From Scratch in GDScript
How I drew a minimap that auto-scales to any procedurally generated track shape, shows gates as coloured dots, and renders online racers with name tags, all in _draw().
Adding Online Multiplayer to a Solo Racing Game
How I added real-time online multiplayer to a web-based Godot racing game using an AWS WebSocket relay, ghost cars, and a shared track seed.
Drift Physics: Making Cars Feel Right Without a Physics Engine
How a CharacterBody3D, a lateral grip constant, and a handbrake multiplier create satisfying arcade drift physics in Godot, no RigidBody required.
How I Built a Procedural Race Track Generator in Godot
A walk through the Catmull-Rom spline trick that builds a unique closed-loop race circuit every time you hit play. And keeps 30 online racers on the same one.