akdarrah 0:posts* 1:archive 2:about
adam@akdarrah~/posts$cat i-built-a-game-with-ai-and-gave-up-on-it.md

I built a game with AI and gave up on it

5 min #ai#games#retro
contents · notes

I spent three days building a multiplayer surf game with Claude Code, and I'm not going to finish it.

Not because it broke. It works: a Rust server that holds two thousand players on a core, a browser client on WebGPU, movement code ported from Counter-Strike so surfing feels like surfing, a level generator that does the physics so the ramps are rideable, bots, chat, rounds, spray walls. It's on GitHub. I'm stopping because after five versions it still isn't the game I had in my head, and I noticed I'd stopped caring whether the next version would be.

That's the post. The rest is what happened and what I think it means.

The idea

If you played Counter-Strike in the 2000s you know surf maps: giant sloped ramps you slide along by strafing, no shooting required, pure flow. I wanted that in a browser tab, massively multiplayer, embeddable in a blog post. And I wanted a viral hook: win a round and your image stays in the level for everyone to see.

Easy to describe. That should have been my first warning.

Five versions in three days

v1 took an afternoon. Sailboats, silly art, low-poly clouds, a popgun with upgrades, six stages, a leaderboard. Win a round and you paint your sail.

v1: a sail you could paint by winning a round. Low-poly clouds, a popgun, a HUD that was one step from Comic Sans.
fig.1 v1: a sail you could paint by winning a round. Low-poly clouds, a popgun, a HUD that was one step from Comic Sans.

It was fine and it was cute, and cute wasn't the feeling I wanted. "Too friendly," I said. Make it grittier, for teenage boys: flags with a sponsor name, uploaded images, sprays, a dark sunset.

v1.1: make it grittier. Sunset, black ramps, flags with sponsor names, flintlocks.
fig.2 v1.1: make it grittier. Sunset, black ramps, flags with sponsor names, flintlocks.

v1.1 did all of that in an hour and I liked it less. It wasn't a game that wanted to be gritty; it was the cute game wearing black.

So I did the thing you do when you can't articulate what's wrong: I asked for everything to be rebuilt from scratch, "modern, wow factor, inspired by classic CS surf maps". v2 dropped the guns, replaced the boats with gliders, added a physical sky, bloom, motion blur, a flythrough lobby, a ghost of the record run, and billboards the winner could advertise on.

v2: the ground-up rebuild. Neon ramps, a physical sky, a lobby flythrough.
fig.3 v2: the ground-up rebuild. Neon ramps, a physical sky, a lobby flythrough.

It looked like a tech demo. It was a tech demo.

v2.1 was my longest list: exact two-minute rounds, no sponsors, free-for-all spray walls instead of billboards, NPC racers so an empty server still feels alive, CS-style chat, a cloud sea thousands of units below the course, floating rocks, and, because I'd just been thinking about Astro Bot, giant creatures in the distance.

v2.1: the course from the lobby flythrough. Floating rocks, a cloud sea, and a podium that said no finishers.v2.1: a painted spray wall. Press T in front of it and your spray stays until someone paints over it.
fig.4 v2.1: the course from the lobby flythrough. Floating rocks, a cloud sea, and a podium that said no finishers. / v2.1: a painted spray wall. Press T in front of it and your spray stays until someone paints over it.
v2.1: a sky leviathan cruising the cloud sea. I had asked for megalophobia.
fig.5 v2.1: a sky leviathan cruising the cloud sea. I had asked for megalophobia.

Each of those shipped. Each one was verified in a browser by the agent itself. And the whole thing still felt like one very long ramp with decorations on it.

v3 is where I finally said what I actually wanted, and it took a reference image to do it: the Iron Giant scene from Astro Bot. Clean cream and blue shapes, warm light, something enormous and calm standing in the clouds. Players as hovering sailboats with their spray on the sail. A join screen that asks for two things. And a real surf map: short ramps, gaps you need speed to clear, forks where a risky line and a safe line split and rejoin.

v3: the join card, down to a name and a spray.
fig.6 v3: the join card, down to a name and a spray.
v3: the start gate, with the giant behind it.v3: the sailboat, with the spray on its sail.
fig.7 v3: the start gate, with the giant behind it. / v3: the sailboat, with the spray on its sail.
v3: cloud islands, and the F3 overlay that proved it ran at 120 fps.
fig.8 v3: cloud islands, and the F3 overlay that proved it ran at 120 fps.

v3 is the closest to the vision, and it's the version I stopped on.

What was actually hard

The parts I expected to be hard were easy. The server, the networking, the WebGPU client, the Source movement port: the agent wrote those in hours and they held up.

The hard part was the level. Not the rendering of it, the design of it. A surf map is a physics argument: the ramp angle, the gap length, the speed you arrive with, and how far sideways you can recover all have to agree, or you fly into nothing. I spent most of the three days watching an autopilot fall off ramps while we figured out, number by number, what the physics allowed:

  • a rider sliding down a ramp face can strafe back toward the ridge at about 800 units/s² on a 51° face, and not much more;
  • every concave pitch change shoves a rider sideways by roughly 0.46 × v² ÷ R, so the easing radius has to be big enough for strafing to keep up;
  • a landing ramp pitched to the slow rider's arrival angle lands the fast rider thousands of units later on a long steep slope, and the course runs away;
  • a full loop has to drop more than its own ramp is deep or it eats its own tail.

The generator now encodes all of that and refuses to build a course it can't prove rideable. That is genuinely nice engineering. It is also not fun, and nothing about measuring it made the game more fun. Fun was the thing I couldn't specify.

The lesson

I had the same realization a while ago about making videos. You watch people do it on social media and it looks effortless, so you try, and you discover the effort was invisible, not absent. Framing, pacing, knowing what to cut. Taste.

Building with AI is the same. Prompting is not the bottleneck anymore; I could describe a feature and have it exist, tested, in a browser, in under an hour. The bottleneck was me. Every version was a correct implementation of what I asked for, and what I asked for was never quite the game, because I didn't know the game well enough to ask. The one time I gave it a picture instead of adjectives, it got close.

Which means the thing that decides whether an AI-built product is good is the same thing that decided it before: whether the person steering has taste for the domain and the motivation to keep refining until it's right. I have taste for software. I don't have it for games, and three days in I didn't have the motivation to acquire it either. The agent would happily have done v4. I'm the one who's done.

If you want to poke at it

The code is at github.com/akdarrah/surfing (branch sky-surf-v2). The README explains the server, the physics port, and the level generator, including the design rules above. If you're the person with the taste for this, it's a surprisingly solid base for a surf game. Just don't ask me to make the ramps fun.

share
view .md
↑↓ move↵ open` shellesc close
akdarrah0:posts1:archive2:about3:shell* esc close
adam@akdarrah~$help
  ls [posts|tags]   list things      cat <slug>   open a post
  grep <word>       search           art [scene]  draw something
  tree              the old bonsai   subscribe <email>