Vibe Arcade Blog

Dev stories, game design, and the art of building with AI

Tilt: How We Built the AI-Coded Pinball Game

A single hand-crafted table. Hand-rolled 2D physics with no library. And the flipper bug that three rounds of code review could not catch, because code review cannot see a flipper swing the wrong way.

· Vibe Arcade

game dev pinball vibe coding 2D physics behind the scenes

Pinball is a strange category to attempt with AI. Most arcade genres break down cleanly into rules and states: snake has a grid and a direction vector; brick breakers have a paddle and a ball with reflection math; space shooters have enemies and projectiles. Pinball has a single ball and a table, and the entire game is the feel of the ball moving through the table. You cannot unit-test feel. You have to build it, play it, and rebuild the parts that feel wrong.

Tilt is our attempt. A single 600 by 900 hand-crafted playfield, retro pixel visuals with a CRT scanline overlay, hand-rolled 2D physics with no library, and the classic pinball grammar intact: five bumpers, a three-target drop bank, two slingshots, two flippers, a plunger lane, a skill shot, and multiball. The name comes from the old electromechanical machines that would flash TILT WARNING and lock the flippers if you shook the cabinet too aggressively. Tilt has that too.

Want to play first, then read the build story?

▶ Play Tilt Now

Why a Single Hand-Crafted Table

The first temptation when building a pinball game with AI is to make the table procedural. Let the generator decide where bumpers go, where the drop targets sit, how the slingshots angle. It sounds elegant. It does not work.

Pinball is composed. Every real-world table is an authored object where the designer placed each bumper to feed the ball into a specific lane, angled each slingshot to kick the ball back toward the flippers rather than into the drain, and tuned the ramp entry so a clean shot pays off. Procedural generation optimizes for variety, but pinball design optimizes for flow. A randomly generated table is almost guaranteed to be worse than a mediocre hand-designed one, because the geometry of pinball is about intentional relationships between objects.

So we wrote out the coordinates by hand, up front. Five bumpers — three clustered near the top of the table, two more lower down mid-field. Three drop targets in a row across the upper mid-field. Two slingshots tight above the flippers. The plunger lane on the right. Angled outer walls that funnel the ball toward the flipper gap. Every element had an x, y, and radius specified in a table before any code was written. The physics code only had to handle ball-vs-circle, ball-vs-line-segment, and ball-vs-rectangle. The layout itself was the design document.

Hand-Rolling 2D Physics Without a Library

Tilt uses no physics library. Not Matter.js, not Box2D, nothing. The reasoning was partly size (single HTML file, no external scripts) and partly control (pinball feel is about specific restitution values, and libraries abstract those away). The whole physics runtime is maybe a hundred lines of code.

Three collision routines do all the work:

The interesting part was the flipper. A flipper is a line segment that rotates around a fixed pivot. When the flipper is swinging up, the ball contact point on the segment is moving too, and its velocity is angular velocity times distance from the pivot. Adding a fraction of that contact velocity back into the ball after reflection is what produces the scoop effect. Get it wrong and the flippers feel limp, or they launch the ball into orbit. We tuned the multiplier by playing until it felt right.

Preserving Pinball Grammar

There is a vocabulary that pinball players expect, and a game that drops any of it starts to feel like pinball-flavored rather than actual pinball. Tilt keeps the full set:

The skill shot rewards a bumper hit within two seconds of launch. This is the classic "aim your plunger" mechanic every real table has, where the first few moments after launch are a high-risk, high-reward opportunity if you know where to aim. We added a glowing floating text callout when it triggers so new players learn what just happened.

The drop-target bank is three targets in a row. Each one awards points when hit, and clearing all three gives a large ALL CLEAR bonus with a celebration arpeggio. The targets then reset and the bank is live again. This is the closest thing Tilt has to a mid-game goal beyond raw scoring: chase the bank, clear it, repeat.

The combo multiplier scales up as you chain scoring hits — bumpers, drop targets and slingshots all count — within a one-second window of each other. Every two combo steps raises the multiplier, which caps at 5x, and the visual treatment escalates as you climb: the screen shake is larger, the particle count is higher, the multiplier HUD grows and color-shifts from magenta toward gold, and a progress bar shows how close you are to the next level. Chaining feels like chaining, not like a number quietly incrementing.

Finally, multiball triggers at a threshold score. Two extra balls spawn from the top of the table and the point value of everything briefly matters more. When you drop down to one ball again, there is usually a visible dip in score gain, and the goal becomes getting back to multiball. This is classic pinball pacing: long periods of grinding punctuated by peak moments.

The CRT Look Without the CRT Complexity

The aesthetic target for Tilt was a chunky pixel-art pinball table viewed through an old CRT monitor. Full CRT simulation means shader passes, phosphor persistence, RGB mask patterns, barrel distortion. On a browser canvas that has to run on a tablet, that is not happening.

The simplified version is a fixed-position pseudo-element overlay with a repeating linear-gradient that alternates two transparent pixels with two of magenta at one percent opacity, producing horizontal scanlines across the entire viewport. Paired with pixel-accurate shapes (chunky bumpers, dot-matrix-style score display, crisp line walls) and a dark navy background, it reads as CRT without costing anything on the GPU. The bumpers use flat color fills, no gradients on animated objects, no drop shadows. Cheap to render, consistent on every device we tested.

The Bug Code Review Could Not See

The most useful lesson from building Tilt was a limit of AI-driven QA. Our overnight game pipeline has a code-review pass that scores each iteration across six dimensions: playability, visual quality, fun factor, code quality, mobile compatibility, and integration. It works well for many games. It cannot see a flipper.

For three iterations, the right flipper was visibly inverted on screen. At rest, its tip pointed up. When activated, it swung down. A player watching the game would see it immediately. The QA agent, which reviews code and structure without rendering the game, scored visual quality at 9 out of 10. The sign convention on one flipper's rest angle was simply wrong, and nothing in the static review caught it.

Two other physics bugs shipped through the same way. The plunger lane was a sealed dead-end on the first few iterations: the top-right wall ran continuously from the corner down to the flippers, so any launched ball bounced off the wall and fell right back into the lane. It could not enter the playfield. And the plunger launch speed was tuned below what was needed to clear the new diagonal hood we added to fix the dead-end, so balls that did make it out were too slow to reach the upper bumpers.

All three of those issues are the kind that take thirty seconds to spot with a real playtest. They are nearly impossible to spot by reading code, because the code looks syntactically fine and the sign convention question depends on what you consider "up" in canvas coordinates (where y grows downward). The fix was not better code review. The fix was adding a playtest step that actually launches a ball and traces its path. The lesson we took forward: physics games need human eyes on the output, not just AI eyes on the source.

Polish on a Working Core

Once the physics were right, we spent an iteration just layering feel. Most of it is invisible individually, but collectively it is the difference between a playable pinball game and one that people replay.

The ball trail is a five-frame ghost of previous positions, with the color interpolating from cool cyan at low speed to hot magenta at high speed. You feel the ball gathering energy as it drops from the top of the table. Screen shake on bumper hits scales with the current combo multiplier, from a gentle 4-pixel jiggle at 1x to a proper 8-pixel thud at 5x. Haptic vibration on mobile fires on every significant event: flipper tap, bumper hit, skill shot, drop target, drain, slingshot. Each one has its own vibration pattern so your palm can tell them apart. Pause-on-blur means you can answer a text without losing a ball.

None of this is specific to AI-assisted development. It is the last 20% of polish that separates shipped games from proof-of-concepts, and it is the stage where tight iteration matters most. The AI handled the boilerplate of particle systems, HUD scaling, and vibration API guard clauses quickly enough that we could spend the time on the taste-level decisions: does this feel right, does it feel wrong, try another value.

What Pinball Taught Us

Tilt is probably the game in the Vibe Arcade collection where the AI had the least design latitude. A snake game can absorb a ten-snake roster and a mission tree without breaking. A pinball game cannot absorb arbitrary features. Every object on the table either makes the ball do the right thing or it breaks flow. The design was a hand-authored coordinate table, and the AI's job was to implement the physics correctly and then polish the feel.

That division of labor turned out to work well. The parts where AI assistance accelerated us most were the boilerplate physics routines, the HUD layout, the sound synthesis, and the mobile touch handling. The parts that still required human judgment were the table layout, the physics constants, and catching the playtest bugs that static review could not see. Pinball is a reminder that not every game should be designed by its implementer. Sometimes the right brief is a very specific spec, and the interesting work is making that spec real.

Play Tilt and see if you can trigger the skill shot on your first launch.


Related reading: How We Built Neon Snake With AI · What Is Vibe Coding? · Vibe Coding Tools: From Chatbots to AI IDEs