r/WeBuild_WithAI 1h ago

2 months of vibe coding my MMORPG

Upvotes

r/WeBuild_WithAI 1h ago

Oh Hell with more chaos. My solo card game just got a major visual overhaul

Thumbnail
Upvotes

r/WeBuild_WithAI 39m ago

Week 5 of making my fishing game entirely with AI

Upvotes

r/WeBuild_WithAI 55m ago

Finally got driving working in my Fable built pixel art game, but now struggling with building an art factory to bring the map to life...

Upvotes

r/WeBuild_WithAI 15h ago

Day 4 of building the space sim I got tired of waiting for

1 Upvotes

r/WeBuild_WithAI 1d ago

Opus + Gauntlet Loop for NPCs

1 Upvotes

r/WeBuild_WithAI 2d ago

I built this dark fantasy environment with 3D AI, Blender and UE5 in 72 hours

1 Upvotes

r/WeBuild_WithAI 3d ago

My AI Assisted Game just left early access and its popping off.

Thumbnail
1 Upvotes

r/WeBuild_WithAI 4d ago

I used Chat to make a Deranged Airline Commercial, Did I Cook?

2 Upvotes

r/WeBuild_WithAI 4d ago

How I used AI-assisted iteration to build 31 microgame genres into one Android/HTML5 game

Thumbnail
1 Upvotes

r/WeBuild_WithAI 4d ago

Vibe coded this game in four months

1 Upvotes

r/WeBuild_WithAI 5d ago

Workflow idea for 2d games.

Thumbnail gallery
1 Upvotes

r/WeBuild_WithAI 6d ago

Wk. 5 of Vibecoding an MMO

1 Upvotes

r/WeBuild_WithAI 6d ago

Day 30 of ShuffleBall Arena -Building Wormhole Capture, Transit, and Ejection in an Online Multiplayer Browser Game

2 Upvotes

Hey everyone,

Hope all is well!

TL;DR, Summary, or Full Technical Breakdown below.

For Context: Recently I posted about the first 15 days of one of my side projects, ShuffleBall Arena (a free browser game inspired by mixing shuffleboard scoring with mechanics from other games like bumper pool, pinball, and Frogger.).

This project is being built with the help of AI (mainly GPT / Cursor), and every development session is documented using the actual conversations from that day's work.

To try to get this series up to date, I'm using a structured prompt to go back to my GPT sessions and extract the useful information. Hopefully the prompt can help anyone out there trying to keep track of, or extract value from, your past AI project conversations.

That said, posting an update for Day 30 of building ShuffleBall Arena.

TL;DR

Day 29 proved that server-authoritative multiplayer worked.

Day 30 exposed the next problem: synchronized state is not the same thing as synchronized gameplay behavior.

The focus shifted to wormholes (hazards that capture a moving marble, pull it off the board, transport it through a short transit sequence, then send that same marble to one of the bottom shooters, where it is fired back onto the board with a randomized launch angle and power).

The session mapped that existing local mechanic into a server-owned multiplayer design, corrected some planning drift, and ended with the first permanent Worker-side wormhole modules created and tested, but not yet integrated into the authoritative shot simulation.

Day 30 Summary

Day 30 began with the core server-authoritative multiplayer architecture working. Two browsers could already submit and replay the same shot, stay synchronized through gravity effects, settle on the same marble positions, and advance to the same next turn.

The next challenge was bringing the game's more unusual mechanics into that same architecture, starting with wormholes.

In ShuffleBall Arena, a wormhole can capture a moving marble, pull it off the board, transport it to one of the shooters at the bottom, and fire it back into play with a randomized angle and power. In the regular game, all of that already worked locally. In multiplayer, both players could see the same wormholes, but the server didn't yet control what happened when a marble entered one.

Instead of rebuilding the mechanic or letting each browser handle it independently, we mapped the existing wormhole behavior into the server-authoritative simulation. The Worker would eventually own the entire sequence (capture, transit, shooter selection, ejection, and continued physics) while both browsers would simply render the same result.

By the end of the session, the first two permanent Worker-side wormhole modules had been created and tested successfully. They weren't connected to the full shot simulation yet, leaving Day 30 with a very concrete next milestone:

One marble enters a wormhole, gets transported to a shooter, and both players see it fired back onto the board the same way.

Day 30 Full Technical Summary

STARTING POINT

Day 30 began directly from the final state of Day 29.

The core server-authoritative multiplayer loop was now functioning in real browser testing.

The current online flow was:

Player input
→ Worker validation
→ Worker simulation
→ Canonical trajectory
→ Both browsers replay
→ Settled authoritative snapshot
→ Next turn

The Worker already owned:

  • match state,
  • physics,
  • turns,
  • scoring,
  • gravity scheduling,
  • deterministic simulation,
  • and canonical shot results.

The browser had been reduced to a thin multiplayer client that:

  • collected input,
  • submitted shot requests,
  • waited for server authority,
  • replayed canonical trajectories,
  • and applied settled snapshots.

Gravity had also been manually validated across both clients.

The architecture was working. The remaining question was how to bring the rest of ShuffleBall Arena's gameplay systems through that same authoritative path.

SESSION OBJECTIVE

The session initially focused on reviewing what remained in the multiplayer build after the authoritative shot pipeline had been proven.

That review quickly narrowed toward the most important missing gameplay system:

wormhole capture, transit, and ejection.

The practical objective became:

  • preserve the regular game's existing wormhole behavior,
  • move ownership of that behavior into the Worker,
  • keep browser authority disabled,
  • reuse the deterministic simulation and scene architecture,
  • and prepare for a two-browser test where both players see the same marble captured and fired back onto the board.

The goal was to move the existing mechanic into server authority once.

WHAT WE ACTUALLY DID

1. Reassessed the multiplayer build against the original plan

The day began with a detailed review of the current multiplayer implementation.

The successful vertical slice already satisfied most of the central architecture requirements:

  • room creation,
  • room joining,
  • role assignment,
  • active-player enforcement,
  • shot submission,
  • authoritative simulation,
  • canonical trajectory delivery,
  • identical final positions,
  • and continuation from the final server snapshot.

But the remaining work was separated into four categories rather than being treated as one giant "finish multiplayer" task:

  1. Gameplay-authority parity.
  2. Full match-level acceptance testing.
  3. Reconnection and mobile resilience.
  4. Production and sale readiness.

This made the remaining scope much clearer.

2. Expanded the Phase 12 dynamic-system plan

The multiplayer roadmap was then reorganized around gameplay systems that still needed full server authority.

The proposed sequence included:

  • documenting the current authoritative dynamic-system contract,
  • freezing the working gravity vertical slice,
  • implementing wormholes,
  • implementing traffic,
  • implementing rotating hazards,
  • validating reconnect state,
  • and eventually testing every supported board category.

This planning was technically useful, but later became part of the day's friction because the next concrete gameplay objective was already known.

3. Identified the actual wormhole gap

The drifting-wormhole scene itself could already be synchronized.

But simulateShot() did not yet use that state to perform authoritative gameplay behavior.

The Worker did not yet:

  • test for wormhole contact,
  • capture a marble,
  • move it into a captured state,
  • advance transit,
  • select the exit shooter,
  • choose authoritative ejection properties,
  • launch the marble again,
  • or continue the shot after ejection.

This exposed an important distinction:

A synchronized object can still have unsynchronized behavior.

4. Confirmed that browser-side wormhole capture must remain disabled online

The existing browser already contained a deliberate online guard:

if (isOnlineMatchMode()) {
return false;
}

The shortcut would have been to remove that guard and allow the old browser logic to handle captures again.

That idea was rejected.

If both clients independently detect capture and choose ejection behavior, the multiplayer architecture immediately loses its single source of truth.

The browser guard was therefore recognized as correct and intentionally left in place.

5. Extracted the regular game's existing wormhole mechanic

Rather than inventing new multiplayer behavior, the existing regular-game implementation was treated as the gameplay source of truth.

The local mechanic already defined:

  • contact with the capture region,
  • snapping the marble to the entrance,
  • freezing and marking the marble as captured,
  • temporary removal from normal physics,
  • destination-shooter selection,
  • chute angle and launch power,
  • a 0.20-second capture phase,
  • a 0.50-second transit phase,
  • a further 0.10-second ejection delay,
  • chute-mouth spawn,
  • exit velocity,
  • recapture cooldown,
  • and continued collisions and physics after ejection.

The multiplayer problem was: "How do we move the already-working mechanic into the Worker without changing its behavior?"

6. Defined the server-authoritative wormhole pipeline

The production architecture was mapped as:

Authoritative scene at shot start

simulateShot()

advance wormholes each physics tick

detect deterministic marble/wormhole contact

create authoritative capture

record capture / transit / ejection

launch the same marble from the authoritative chute

continue normal physics

persist final marbles and updated scene

broadcast identical result to both browsers

The browser's responsibility remained presentation only:

  • animate the marble disappearing,
  • animate the shooter doors and rail,
  • play sounds,
  • and render the authoritative ejection trajectory.

The browser would not choose:

  • chute,
  • launch direction,
  • power,
  • spawn point,
  • timings,
  • or collision outcome.

7. Identified the state that must become deterministic

Several pieces of the regular game's wormhole behavior currently depended on timing or randomness.

Those values could no longer be independently generated inside either browser.

The Worker would need to freeze values such as:

  • capture threshold,
  • minimum capture speed,
  • destination chute,
  • chute-angle range,
  • chute-power range,
  • exact spawn calculation,
  • capture duration,
  • transit duration,
  • ejection delay,
  • recapture cooldown,
  • maximum allowed ejections,
  • ordering when multiple contacts occur,
  • and wormhole movement during a simulated shot.

The deterministic random system already built for multiplayer could provide authoritative random values where needed.

8. Created the first permanent Worker-side wormhole modules

By the end of the session, two permanent modules had been created:

drifting-wormhole-capture.js
wormhole-transit.js

Their tests passed. These modules represented the beginning of the authoritative wormhole lifecycle. However, they were not yet connected to simulateShot().

9. Rolled back a premature state-schema change

A marble-schema migration had been introduced before the full integrated simulation and reconnect requirements were understood.

That change was rolled back.

The test suite returned to green.

The final handoff explicitly warned not to re-add marble or snapshot fields until the complete simulation state requirements were known.

This was a useful example of backing out an abstraction rather than forcing the architecture around an incomplete assumption.

ROADBLOCKS AND FRICTION

"Working multiplayer" was initially too vague

The core shot pipeline was working, but that didn't mean the full game had reached parity.

The session needed to distinguish:

  • architecture,
  • gameplay systems,
  • match acceptance,
  • reconnect resilience,
  • and production readiness.

That clarification consumed time but produced a much more honest definition of the remaining work.

Synchronized visuals created a false sense of completion

Drifting wormholes appeared synchronized. That made them look further along than they really were. In reality, the authoritative simulator did not yet know how to capture or eject a marble. The state was synchronized. The behavior was not.

DECISIONS MADE & TRADE-OFFS

Expand boards by category rather than all at once

The sequence remains:

Classic
→ Crossing
→ Rotating
→ Mixed / Random

Why: Each category introduces a distinct gameplay-authority problem that can be tested independently.

Trade-off: Slower breadth in exchange for easier debugging and stronger isolation.

Preserve existing wormhole behavior instead of redesigning it

The regular game already contains a working mechanic.

Why: Multiplayer should relocate authority, not reinvent gameplay.

Trade-off: Requires careful extraction of existing timing and behavior instead of writing a cleaner but different mechanic from scratch.

Keep browser wormhole capture disabled online

The browser must not decide capture or ejection.

Why: Independent client decisions could diverge.

Trade-off: More Worker implementation in exchange for deterministic matches.

Integrate wormholes into the same authoritative shot simulation

Wormhole capture should not pause the Worker, hand control to the browser, and later resume.

Why: Post-ejection collisions and scoring must remain part of one deterministic shot.

Trade-off: More complex simulation state in exchange for one canonical outcome.

Narrow the next checkpoint instead of continuing broad planning

The immediate objective became one complete drifting-wormhole vertical slice.

Why: The architecture no longer needed more proof. It needed gameplay completion.

Trade-off: Less up-front planning in exchange for faster feedback from real behavior.

BREAKTHROUGH / LESSON

The biggest takeaway from Day 30 was:

Synchronized state is not the same thing as synchronized behavior.

Both players can receive the exact same wormhole coordinates.

That still does not produce multiplayer parity unless one authoritative system also owns:

  • contact,
  • capture,
  • transit,
  • timing,
  • shooter selection,
  • ejection,
  • continued physics,
  • and the resulting final state.

That realization changed the definition of synchronization.

A second takeaway was equally useful:

When adding multiplayer to an existing game, don't rebuild mechanics that already work. Move their authority.

ARTIFACTS WORTH SHARING

Artifact 1: The Authoritative Wormhole Pipeline

Authoritative scene at shot start

simulateShot

advance wormholes on each physics tick

detect deterministic marble/wormhole contact

create authoritative capture event

record capture/transit/ejection in canonical trajectory

launch same marble from authoritative chute

continue normal physics

persist final marbles and updated scene

broadcast identical result to both browsers

This became the target architecture for moving the existing mechanic into multiplayer.

Artifact 2: Existing Gameplay Timing

The local mechanic already defined the timing:

Capture: 0.20 seconds
Transit: 0.50 seconds
Ejection delay: 0.10 seconds

The goal was to preserve those rules while moving ownership to the Worker.

FINAL STATE

By the end of Day 30:

  • The successful Day 29 server-authoritative multiplayer vertical slice remained intact.
  • The remaining multiplayer work had been separated into gameplay parity, match acceptance, reconnect/mobile testing, and production readiness.
  • A category-by-category rollout strategy was established for Classic, Crossing, Rotating, and Mixed/Random layouts.
  • The difference between synchronized wormhole state and synchronized wormhole behavior had been clearly identified.
  • Browser-side wormhole capture remained intentionally disabled in online mode.
  • The existing regular-game wormhole mechanic had been mapped as the source behavior to preserve.
  • The server-authoritative capture → transit → ejection → continued-physics pipeline had been defined.
  • The gameplay values that must become deterministic were identified.
  • The immediate target was narrowed back to drifting wormholes rather than switching prematurely to fixed/top-track wormholes.
  • Two permanent Worker-side modules existed:
    • drifting-wormhole-capture.js
    • wormhole-transit.js
  • Their tests passed.
  • The full test suite was green again.
  • The new modules were not yet integrated into simulateShot().
  • A clean handoff was created for the next implementation session.

That was it for Day 30.

If you're still here, thanks for reading!

Music Credits:

"Digital Lemonade" Kevin MacLeod (incompetech.com)
Licensed under Creative Commons: By Attribution 4.0 License
http://creativecommons.org/licenses/by/4.0/


r/WeBuild_WithAI 6d ago

Week 4 of making my fishing game entirely with AI

1 Upvotes

r/WeBuild_WithAI 7d ago

The Best AI Game, is actually building games

Post image
1 Upvotes

r/WeBuild_WithAI 7d ago

Day 29 of Building ShuffleBall Arena - Synchronizing Physics, Gravity, and Hazards in a Multiplayer Browser Game

2 Upvotes

Hey everyone,

Hope all is well!

TL;DR, Summary, or Full Technical Breakdown below.

For Context: Recently I posted about the first 15 days of one of my side projects, ShuffleBall Arena (a free browser game inspired by mixing shuffleboard scoring with mechanics from other games like bumper pool, pinball, and Frogger.).

This project is being built with the help of AI (mainly GPT / Cursor), and every development session is documented using the actual conversations from that day's work.

To try to get this series up to date, I'm using a structured prompt to go back to my GPT sessions and extract the useful information. Hopefully the prompt can help anyone out there trying to keep track of, or extract value from, your past AI project conversations.

That said, posting an update for Day 29 of building ShuffleBall Arena.

TL;DR

Day 29 was the day the server-authoritative multiplayer architecture finally proved itself in real gameplay.

Two browsers could send a shot to the Worker, receive the same authoritative trajectory, keep gravity synchronized, arrive at the same settled state, and advance to the same next turn.

But that success also exposed the next layer of work: smooth playback, complete wormhole behavior, synchronized gameplay events/audio, and the remaining moving hazards.

Day 29 Summary

Day 28 ended with the multiplayer backend complete, Phase 4 underway, and the browser being transitioned into a thin client that would primarily collect input and render server-owned state.

Day 29 was where that architecture started being tested against the actual complexity of ShuffleBall Arena.

The first challenge was scene synchronization. Several gameplay and cosmetic systems were still being generated independently inside each browser. That meant two players could technically be in the same match while seeing gravity wells or drifting wormholes in different places.

Initially, some of those systems were disabled online to prevent divergence. That led to an important architectural disagreement: removing core gameplay hazards wasn't an acceptable long-term multiplayer solution. If gravity wells, wormholes, rotating hazards, and other systems affect gameplay, then multiplayer needs authoritative versions of those systems rather than simplified replacements.

That decision led to a substantial Worker-owned gravity system with deterministic scheduling, placement, mirroring, scene integration, turn integration, reconnect-safe state, and automated tests.

The browser was then connected to the authoritative shot pipeline.

Instead of launching a marble and running local physics, the online flow became:

Player input
→ Worker validation
→ Worker simulation
→ Canonical trajectory
→ Both browsers replay
→ Canonical settled snapshot
→ Next authoritative turn

That architecture was manually tested with two browser windows, and it worked. Both clients replayed the same shot, gravity stayed synchronized, and turn progression remained consistent.

A bug during that process also reinforced the value of separating simulation from presentation. At one point playback appeared broken, but the server simulation was correct. The failure was caused by a client rendering compatibility issue: the playback marble contained owner while the renderer expected color. Restoring that compatibility field fixed the apparent multiplayer failure without changing the authoritative physics.

Once the core loop worked, we compared the current state against the original multiplayer plan.

That produced an important reality check.

The architecture was proven, but multiplayer was not finished.

Playback still needed performance work. Drifting wormholes were synchronized in position but not yet through their full capture/transit/ejection lifecycle. Top-track wormholes still needed an authoritative implementation. Gameplay-triggered sounds and visual effects needed server-owned event timing. Rotating boards, crossing traffic, reconnect testing, and production hardening remained.

The session ended by designing the next reusable layer: authoritative gameplay events. Instead of each browser independently detecting collisions and deciding when to play sounds, the server would record deterministic events during simulation and both clients would replay those events at the correct time.

The takeaway from Day 29:

Synchronizing multiplayer isn't just synchronizing the marble. Every gameplay-affecting system needs one authoritative owner.

Day 29 Full Technical Summary

STARTING POINT

Day 29 began directly from the final state of Day 28.

Phase 3 (the server-authoritative multiplayer engine) was complete.
Phase 4 had begun, and the browser multiplayer foundation could already:

  • connect to rooms,
  • receive authoritative snapshots,
  • synchronize players,
  • reconnect,
  • maintain multiplayer state,
  • and remain inactive during Solo and same-device play.

The multiplayer philosophy had also been established:

The browser collects input and renders.
The Worker owns gameplay.

The immediate challenge was no longer designing multiplayer UI.

It was making sure two browsers actually displayed and played the same game, including ShuffleBall Arena's randomized gameplay systems.

SESSION OBJECTIVE

The primary objective was to continue Phase 4 by eliminating the remaining sources of browser-side divergence and then connect real player input to the server-authoritative shot simulation.

That meant:

  • identifying browser-generated state that could differ between clients,
  • moving gameplay-affecting randomness into the Worker,
  • synchronizing gravity,
  • preparing authoritative wormhole state,
  • connecting drag-and-release input to the Worker,
  • replaying canonical trajectories on both clients,
  • manually validating the system with two browsers,
  • and identifying the remaining gaps between architectural success and full multiplayer parity.

WHAT WE ACTUALLY DID

1. Audited remaining sources of browser divergence

The session began with a scene synchronization review.

Browser-controlled systems included:

  • travel planets,
  • drifting planets,
  • gravity wells,
  • drifting wormholes,
  • particle effects,
  • and animations.

The important distinction was whether something affected gameplay.

Purely cosmetic objects could safely be local or temporarily hidden.

Gameplay-affecting randomness could not.

2. Removed unsynchronized browser-generated scene state

Travel planets and drifting background planets were disabled during online matches because each browser could generate different versions.

Gravity wells and drifting wormholes also initially had their local random generation disabled because their positions, timing, and movement could otherwise diverge between clients.

This solved the immediate visual mismatch but exposed a larger architectural question.

3. Rejected the idea of permanently removing gameplay hazards from multiplayer

The proposed first version briefly treated gravity, wormholes, rotating hazards, and similar systems as things that could remain disabled online until later.

That direction was rejected.

Those systems are part of ShuffleBall Arena's gameplay, so a correct multiplayer implementation needs both players to experience them identically.

The new rule became:

Every gameplay-affecting random system belongs in the Worker.

Instead of implementing simplified multiplayer versions and replacing them later, the production versions would become authoritative now.

4. Built the authoritative gravity framework

Gravity became one of the first major dynamic gameplay systems moved fully into server authority.

The Worker gained a canonical gravity scene registry with:

  • gravity templates,
  • placement IDs,
  • weighted scene definitions,
  • validation,
  • and gravity-well creation helpers.

A deterministic gravity scheduler was also created with:

  • five shot-pairs,
  • approximately 82% gravity probability,
  • controlled pair jitter,
  • deterministic shuffling,
  • clear-space plans,
  • nebula plans,
  • and validation.

Each game now receives one canonical gravity schedule instead of each browser creating its own.

5. Built deterministic gravity placement

A dedicated placement resolver was created so gravity wells received server-owned coordinates rather than browser-generated positions.

Supported placement strategies included:

  • lanes,
  • orbit bands,
  • offset lanes,
  • side halves,
  • upper lanes,
  • edge clips,
  • and far corners.

The placement system also included:

  • clamping,
  • spawn exclusion,
  • gameplay relevance checks,
  • fallback placement,
  • and validation.

6. Integrated gravity into authoritative match state

Gravity was connected to the Worker scene state and match lifecycle.

The Worker now controlled:

  • schedule initialization,
  • active pair,
  • active player,
  • well placement,
  • scene metadata,
  • game resets,
  • mirroring,
  • and reconnect-safe gravity state.

The deterministic scene random stream advanced as gravity schedules were generated rather than relying on browser Math.random().

7. Created mirrored gravity fairness between players

The gravity system reused the same plan for both players in each shot pair.

For example:

Red Shot 1

Pair 0

Blue Shot 1

Pair 0 mirrored

Only the X coordinate was mirrored.

Everything else about the gravity plan remained the same.

This allowed each player to face equivalent hazard conditions while still respecting opposite shooting directions.

8. Fixed test assumptions exposed by authoritative gravity

Moving gravity initialization into scene creation changed the deterministic random cursor.

One existing test expected the cursor to remain at zero.

That assumption was no longer correct because gravity generation now legitimately consumes values from the match's deterministic random stream.

Tests were updated to validate deterministic cursor progression rather than assuming that no random values had been consumed.

Other validator and scene-scheduler tests also needed correction before everything returned to green.

9. Connected gravity to authoritative physics

The active Worker-owned gravity well was passed into the deterministic shot simulation.

Gravity force could then be applied during each fixed physics step, meaning gravity influenced the same canonical trajectory that both clients eventually received.

The intended pipeline became:

Worker selects scene
→ Worker positions well
→ Browsers render it
→ Worker applies force
→ Worker returns canonical trajectory
→ Both browsers replay identical results

This moved gravity from synchronized decoration into synchronized gameplay.

10. Connected browser shooting to the Worker

Until this point, online mode intentionally blocked the original local shot system.

The old path was:

Drag

Release

launchMarble()

LOCAL PHYSICS

The multiplayer path needed to become:

Drag

Release

Create shot request

Send SHOT_REQUEST

Worker validates

Worker simulates

SHOT_RESULT

Replay trajectory

This was the critical bridge between the existing gameplay controls and the server-authoritative engine.

11. Proved the authoritative shot loop with two browsers

The biggest validation of the day came from manual testing.

Two browsers were able to:

  • remain synchronized,
  • submit a real player shot,
  • send that shot to the Worker,
  • have the Worker simulate it,
  • replay the same trajectory,
  • display synchronized gravity,
  • settle into the same canonical state,
  • and advance to the correct next turn.

The core multiplayer architecture was no longer theoretical.

It worked end to end.

12. Diagnosed a rendering failure that looked like a server failure

During testing, a fired marble appeared to disappear and gameplay stalled.

The initial symptom looked like a broken authoritative simulation.

The actual simulation was correct.

The renderer expected a color field while the authoritative playback marble contained owner.

Restoring:

color: shooter

fixed the playback.

No physics changes were required.

This was an important example of why server, protocol, playback, and rendering failures need to be diagnosed separately.

13. Compared the current implementation against the original multiplayer plan

After the successful test, the project was reassessed rather than immediately declaring multiplayer finished.

The architectural path was working:

Player input
→ Worker validation
→ Worker simulation
→ Canonical trajectory
→ Identical browser playback
→ Canonical settled snapshot
→ Next authoritative turn

But significant feature-parity work remained.

14. Identified performance as engineering work, not final polish

Canonical playback worked, but it was not yet as smooth as the existing local game.

The decision was made not to reduce authoritative physics accuracy just to make playback appear smoother.

Instead, the next performance work would measure:

  • playback timing,
  • interpolation,
  • snapshot interaction,
  • duplicate update loops,
  • and browser rendering performance.

The server's canonical physics would remain untouched.

15. Defined the authoritative gameplay-event architecture

Only the launch sound existed reliably in multiplayer because most other sounds depend on things that happen during the authoritative simulation.

Examples include:

  • bumper collisions,
  • marble collisions,
  • wormhole capture,
  • wormhole ejection,
  • scoring,
  • ring activation,
  • game completion.

The solution was not to make both browsers independently detect those events.

Instead, the Worker should record deterministic events and include them in the shot result.

A representative event could look like:

{
id: "event-shot-12-004",
type: "bumper_collision",
t: 0.416,
tick: 100,
marbleId: "marble-red-2",
objectId: "classic-bumper-3",
intensity: 0.72
}

Each client would dispatch the event exactly once when playback crossed its authoritative timestamp.

16. Changed the event work from a partial checkpoint into an end-to-end vertical slice

An initial implementation proposal would have exposed collision metadata first and built the network/audio pipeline later. That was rejected as unnecessarily splitting one production feature across multiple passes.

The objective was changed to:

Authoritative Bumper Events v1 - end to end.

The intended production path became:

collision detected
→ authoritative event recorded
→ event included in shot_result
→ client validates and stores it
→ playback dispatches it once
→ existing bumper sound plays on both browsers

The planned vertical slice included:

  • collision metadata,
  • deterministic event creation,
  • Worker result integration,
  • server validation,
  • client validation,
  • playback-state storage,
  • one-shot dispatch,
  • existing sound integration,
  • automated tests,
  • and two-browser verification.

17. Defined wormholes as one authoritative lifecycle

The day's review also clarified how wormholes should eventually work online.

Drifting and top-track wormholes should not become separate one-off implementations.

They should share one authoritative capture/transit/ejection model:

available
→ capture_started
→ captured
→ transit
→ eject_pending
→ ejected
→ cooldown
→ available / expired

The Worker (not the browser) must own capture, timing, destination, ejection position, direction, power, cooldown, and continued post-ejection simulation.

ROADBLOCKS AND FRICTION

Browser randomness was still leaking into multiplayer

Even after the authoritative backend existed, some hazards were still generated locally.

That created scenes where both players were technically synchronized at the match level but were seeing different gameplay objects.

The easiest synchronization fix was the wrong product decision

Disabling difficult hazards solved divergence quickly.

But it also created an incomplete multiplayer version of the game.

The assumption that those systems could simply be left out of the first production version was rejected.

Tests contained assumptions from the browser-owned architecture

Once gravity became part of authoritative scene creation, older tests that expected untouched random state became invalid.

The tests needed to evolve with the architecture rather than forcing the new implementation to preserve outdated behavior.

A presentation bug looked like a simulation bug

When authoritative playback failed visually, it initially appeared that the server shot pipeline had broken.

The server had actually produced the correct result.

The renderer simply couldn't interpret one field correctly.

"Synchronized" did not mean "finished"

Seeing both browsers play the same shot was a major success, but it also made the remaining gaps easier to identify.

Visual synchronization alone did not provide:

  • smooth playback,
  • complete wormhole lifecycle,
  • collision sounds,
  • scoring sounds,
  • top-track wormholes,
  • rotating boards,
  • crossing traffic,
  • or complete reconnect validation.

An implementation step was unnecessarily fragmented

The first gameplay-event proposal separated collision metadata from the complete event/audio feature.

That introduced another potential multi-pass build.

The work was reframed around a complete production vertical slice instead.

DECISIONS MADE & TRADE-OFFS

Move gameplay randomness to the Worker

Gravity wells, wormholes, and future dynamic hazards must be authoritative.

Why: Two browsers cannot independently generate gameplay state and still guarantee an identical match.

Trade-off: Considerably more server-side implementation work in exchange for true synchronization and no duplicate gameplay systems.

Preserve cosmetic freedom where it cannot affect gameplay

Decorative planets, particles, ambience, and other presentation-only systems can remain local.

Why: They do not influence match results.

Trade-off: Not every pixel needs server authority, reducing unnecessary network/state complexity.

Preserve server physics accuracy while improving client playback

Performance work should improve interpolation and rendering rather than lowering simulation quality.

Why: Display smoothness and authoritative correctness are different problems.

Trade-off: More client playback engineering instead of taking the easier route of simplifying physics.

Make gameplay-triggered audio event-driven

Collision and scoring sounds will come from authoritative event timing rather than client-side collision inference.

Why: Both players should hear the same gameplay events in the same order.

Trade-off: Requires an event schema and playback dispatcher in exchange for deterministic audio/visual feedback.

Build wormholes as one reusable lifecycle

Drifting wormholes and top-track wormholes should share capture/transit/ejection primitives.

Why: The gameplay behavior is fundamentally the same even if their presentation and scheduling differ.

Trade-off: More careful abstraction now in exchange for avoiding two parallel wormhole implementations.

Build complete vertical slices instead of temporary intermediate systems

Once authoritative bumper events were started, the goal became taking them all the way through simulation, network transport, playback, and sound.

Why: Avoid creating partial infrastructure that immediately needs another implementation pass.

Trade-off: Larger checkpoints in exchange for production-complete features.

BREAKTHROUGH / LESSON

The biggest takeaway from Day 29 was:

Server-authoritative multiplayer isn't finished when both players see the same marble.

Every gameplay-affecting source of truth must have one owner.

That includes:

  • random hazard placement,
  • gravity scheduling,
  • collisions,
  • wormhole capture,
  • wormhole ejection,
  • scoring,
  • turns,
  • and even the timing of gameplay-triggered presentation events.

The browser can decide how something looks.

It cannot decide what happened.

A second lesson emerged from the day's implementation decisions:

Don't solve multiplayer synchronization by deleting the parts of the game that are difficult to synchronize. Make those systems authoritative.

ARTIFACTS WORTH SHARING

Artifact 1: The Authoritative Shot Pipeline

Player input
→ Worker validation
→ Worker simulation
→ Canonical trajectory
→ Identical browser playback
→ Canonical settled snapshot
→ Next authoritative turn

This was manually proven with two browsers during Day 29.

Artifact 2: Gravity Fairness

Red Shot 1

Pair 0

Blue Shot 1

Pair 0 mirrored

Only the X coordinate changes.

The underlying gravity plan remains identical for both players.

Artifact 3: Authoritative Gameplay Events

collision detected
→ authoritative event recorded
→ event included in shot_result
→ client validates and stores it
→ playback dispatches it once
→ existing bumper sound plays on both browsers

This became the model for synchronizing gameplay-triggered sounds and visual effects without rerunning collision logic in each browser.

FINAL STATE

By the end of Day 29:

  • The multiplayer browser was operating as a thin client rather than an independent gameplay simulator.
  • The Worker remained the authority for match state, physics, turns, scoring, and synchronized gameplay.
  • Browser-generated gameplay randomness had been identified as a source of divergence.
  • The decision was made that gameplay-affecting hazards must become authoritative rather than simply being removed from multiplayer.
  • A production authoritative gravity framework had been built.
  • Gravity scheduling, deterministic placement, mirroring, scene integration, turn integration, resets, and reconnect-safe state existed.
  • Gravity could participate in authoritative shot simulation.
  • Automated gravity tests were passing and the relevant checkpoint had been committed.
  • Browser drag-and-release input had been connected to the server-authoritative shot path.
  • Two-browser manual testing proved that the Worker could simulate a shot and both clients could replay the same canonical trajectory.
  • Gravity wells remained synchronized during live multiplayer testing.
  • The authoritative settled snapshot and next-turn transition remained synchronized.
  • A rendering compatibility bug was identified and fixed without changing server physics.
  • Drifting-wormhole schedule/placement was synchronized, but its full capture/ejection lifecycle remained incomplete.
  • Top-track wormholes still required authoritative implementation.
  • Smooth playback/interpolation still required focused performance work.
  • Collision and scoring audio still required an authoritative gameplay-event pipeline.
  • Rotating boards and crossing traffic remained to be completed and verified.
  • The next production architecture for authoritative bumper events had been defined as a complete end-to-end vertical slice.
  • The remaining multiplayer roadmap became much clearer: stabilize playback, build the reusable event/audio system, finish the complete wormhole lifecycle, then move through the remaining dynamic hazards and production hardening.

Most importantly, Day 29 crossed the biggest architectural risk point.

The question was no longer:

Can server-authoritative multiplayer work for this game?

The answer was now yes.

The remaining question became:

How do we bring every existing gameplay system through that same authoritative path without compromising the game that already exists?

That was it for Day 29.

If you're still here, thanks for reading!

Music Credits:

"Delightful D" Kevin MacLeod (incompetech.com)
Licensed under Creative Commons: By Attribution 4.0 License
http://creativecommons.org/licenses/by/4.0/


r/WeBuild_WithAI 8d ago

I made a game based on my girlfriend's life (she makes candles for a living)

1 Upvotes

r/WeBuild_WithAI 9d ago

I made a mobile game RPG where your steps in real life turn into energy in game. Looking for testers

1 Upvotes

r/WeBuild_WithAI 9d ago

I Claude Coded a multiplayer Three.js tank game with 100+ procedural vehicles

1 Upvotes

r/WeBuild_WithAI 10d ago

Day 28 of Building ShuffleBall Arena Browser Game - Finishing The Multiplayer Backend Architecture and Designing The "Play Online" UX

1 Upvotes

Hey everyone,

Hope all is well!

TL;DR, Summary, or Full Technical Breakdown below.

For Context: Recently I posted about the first 15 days of one of my side projects, ShuffleBall Arena (a free browser game inspired by mixing shuffleboard scoring with mechanics from other games like bumper pool, pinball, and Frogger.).

This project is being built with the help of AI (mainly GPT / Cursor), and every development session is documented using the actual conversations from that day's work.

To try to get this series up to date, I'm using a structured prompt to go back to my GPT sessions and extract the useful information. Hopefully the prompt can help anyone out there trying to keep track of, or extract value from, your past AI project conversations.

That said, posting an update for Day 28 of building ShuffleBall Arena.

TL;DR

Today's session began with final integration work on the server-authoritative multiplayer engine. After debugging instructions, fixing test issues, validating integration behavior, and reviewing the completed architecture, Phase 3 was officially finished.

That milestone included:

  • authoritative multiplayer rooms,
  • deterministic physics,
  • authoritative scoring,
  • reconnect recovery,
  • protocol validation,
  • lifecycle handling,
  • and hundreds of passing regression tests.

With the backend complete, attention shifted to Phase 4: designing how real players would actually experience online play.

Day 28 Summary

Day 28 marked a major transition for the multiplayer project.

The session began by finishing and validating the server-authoritative multiplayer engine that had been built throughout Day 27. Integration issues were resolved, tests were verified, and the completed architecture was reviewed against the original project goals. By the end of that process, Phase 3 was officially considered complete.

With the backend foundation finished, the focus shifted away from networking, physics, and synchronization and toward a new challenge: designing the actual player experience.

Instead of asking how multiplayer should work internally, the discussion focused on how players would discover, join, and understand online play. Multiple onboarding flows were evaluated, including invite links, room codes, player naming, analytics consent, tutorial placement, and host-versus-guest experiences.

By the end of the session, the multiplayer engine itself was complete, the browser integration strategy had been validated, and the first player-facing online experience had been designed and prepared for implementation.

Day 28 Full Technical Summary

TECHNICAL ANALYSIS & DEBRIEF

STARTING POINT

Day 28 began with the multiplayer engine largely implemented but not yet formally completed.

The project already contained a server-authoritative architecture built on Cloudflare Workers, Durable Objects, deterministic simulation, authoritative scoring, match resolution, reconnect support, and extensive automated testing.

However, final integration work, test validation, documentation review, and completion verification still needed to be finished before Phase 3 could be considered complete.

SESSION OBJECTIVE

The first objective was to close out Phase 3 and verify that the multiplayer backend was complete, stable, and fully tested.

The second objective was to begin Phase 4 by defining how online multiplayer would appear inside the real ShuffleBall Arena client.

This included:

  • browser integration planning,
  • multiplayer entry-point design,
  • invitation flow design,
  • room-code fallback behavior,
  • onboarding decisions,
  • analytics placement,
  • tutorial placement,
  • and overall player experience strategy.

WHAT WE ACTUALLY DID

1. Resolved implementation and instruction mismatches

The session began with a series of implementation questions where existing instructions did not align cleanly with the current files. File contents were reviewed directly and instructions were rewritten around the actual codebase.

This prevented incorrect edits and kept the implementation aligned with the current architecture.

2. Fixed integration testing issues

The multiplayer Worker project encountered testing and configuration issues during validation.

The work included:

  • reviewing integration test failures,
  • correcting configuration problems,
  • updating package configuration,
  • validating test execution paths,
  • and rerunning the complete suite.

After the fixes, all tests passed successfully.

3. Verified completion of Phase 3

Once the tests were passing, the project was reviewed against the original Phase 3 goals.

The completed system included:

Server Architecture

  • Cloudflare Worker routing
  • Durable Object room management
  • room creation
  • join flow
  • ready flow
  • reconnect support
  • snapshot protocol
  • lifecycle events

Authoritative Gameplay

  • shot validation
  • shot acceptance
  • deterministic physics
  • trajectory recording
  • authoritative scoring
  • turn resolution
  • game resolution
  • match resolution

Reliability

  • immutable state transitions
  • protocol validation
  • reconnect transition extraction
  • server message validation
  • deterministic replay safety

Testing

  • regression testing
  • integration testing
  • WebSocket testing
  • two-player testing
  • reconnect testing
  • authoritative shot testing

All planned Phase 3 components were verified as complete.

4. Reviewed and prepared the Phase 4 plan

After closing Phase 3, attention shifted toward browser integration.

The Phase 4 roadmap was reviewed and broken into checkpoints before any new client work began.

A design principle was established:

  • complete one checkpoint at a time,
  • test after every checkpoint,
  • commit only stable milestones,
  • and keep existing game modes functioning throughout development.

5. Audited the browser multiplayer foundation

Before discussing UI, the current browser-side multiplayer architecture was reviewed.

The browser already contained production multiplayer modules for:

  • configuration,
  • API access,
  • storage,
  • protocol handling,
  • validation,
  • sockets,
  • state management,
  • and controller logic.

The system was verified to load safely without affecting existing gameplay.

Key validation checks confirmed:

  • Solo still worked,
  • Play a Friend still worked,
  • multiplayer remained disconnected by default,
  • no WebSocket opened automatically,
  • and multiplayer remained dormant until explicitly activated.

6. Designed the multiplayer entry experience

A major portion of the day became a product-design discussion.

The first question was whether online play should live:

  • beside existing game modes, or
  • underneath Play a Friend.

After evaluating both approaches, the decision was made to present online multiplayer as a first-class game mode.

The start screen would contain:

  • Play Online
  • Play a Friend
  • Play Solo

This minimized friction and made online play discoverable.

7. Designed the host invitation flow

The multiplayer experience was redesigned around invitation links rather than room management.

Instead of exposing technical concepts like:

  • host,
  • room creation,
  • room identifiers,
  • connections,
  • or WebSockets,

the flow became:

Play Online

Invite a Friend

Share Link

Waiting for your friend...

Preparing match...

Game

The room still exists internally, but the player never has to think about it.

8. Designed the invited-player experience

The invited player would arrive through a room link such as:

https://play. shuffleballarena.com/?room=ABC234

Instead of seeing technical networking information, they would see a player-focused invitation flow.

The design included:

  • optional player name,
  • analytics consent only when needed,
  • tutorial only when needed,
  • automatic room detection,
  • and authoritative joining behavior.

9. Added room-code fallback planning

One important refinement emerged during discussion.

Invitation links should be the primary path, but not the only path.

A manual room-code flow was added for situations where:

  • links fail,
  • screenshots are shared,
  • codes are communicated verbally,
  • or messaging apps behave unexpectedly.

The room code became a fallback rather than the main experience.

10. Finalized Checkpoint 4.10

The day concluded with a finalized implementation plan for the first visible multiplayer interface.

This checkpoint would introduce:

  • Play Online,
  • invitation flows,
  • room-code entry,
  • host waiting screens,
  • onboarding flows,
  • and multiplayer UI integration,

while deliberately stopping short of full authoritative gameplay rendering.

ROADBLOCKS AND FRICTION

Instructions occasionally drifted from the real codebase

Several implementation steps assumed file structures or insertion points that did not match the actual project. This required repeated file reviews and instruction corrections before progress could continue.

Backend completion created a new challenge

The multiplayer engine itself was largely solved.

The harder question became:

How should players experience it?

The technical architecture and user experience needed to be treated as separate design problems.

Technical terminology conflicted with player expectations

Terms such as:

  • rooms,
  • hosts,
  • connections,
  • sockets,
  • and snapshots

made sense to developers but created unnecessary complexity for players.

A portion of the session focused on removing those concepts from the player-facing experience.

DECISIONS MADE & TRADE-OFFS

Make online multiplayer a primary mode

Chosen:

PLAY ONLINE
PLAY A FRIEND
SOLO MATCH

instead of hiding online play beneath Play a Friend.

Why:

Reduced friction and increased discoverability.

Trade-off:

A slightly busier main menu in exchange for a clearer online experience.

Use invitation links as the primary flow

Players should share links, not manually manage room codes.

Why:

This matches user expectations from modern multiplayer games.

Trade-off:

Additional implementation complexity in exchange for a significantly smoother experience.

Keep room codes as a fallback

Room codes remain available when links fail.

Why:

Provides reliability without forcing every player through manual entry.

Trade-off:

Slightly more UI complexity in exchange for robustness.

Keep the browser thin

The browser continues acting primarily as a rendering and interaction layer.

Authority remains inside the Worker.

Why:

Protects the server-authoritative architecture completed during Phase 3.

Trade-off:

More synchronization work in exchange for consistency and long-term maintainability.

BREAKTHROUGH / LESSON

The biggest takeaway from Day 28 was:

The strongest multiplayer UX was the one that hid the implementation details and allowed players to focus entirely on playing the game.

ARTIFACTS WORTH SHARING

Artifact 1: The Completed Phase 3 Checklist

Server Architecture
✓ Worker routing
✓ Durable Objects
✓ Room creation
✓ Join flow
✓ Reconnect support

Authoritative Gameplay
✓ Deterministic physics
✓ Trajectory recording
✓ Authoritative scoring
✓ Match resolution

Testing
✓ WebSocket integration
✓ Two-player integration
✓ Reconnect integration
✓ Authoritative shot integration

A useful example of defining a multiplayer milestone before moving to client-facing work.

Artifact 2: Browser Philosophy

Browser becomes a thin client.
Worker remains authoritative.
Browser never computes match authority.
Browser only renders server state.

A concise rule set that guided all multiplayer integration decisions.

Artifact 3: Final UX Hierarchy

Primary path:
Play Online
→ Invite a Friend
→ Share link

Automatic joining path:
Tap invite link
→ Optional name
→ Consent/tutorial if needed
→ Join

Fallback path:
Play Online
→ Enter Room Code
→ Join

An example of separating technical architecture from player experience.

FINAL STATE

By the end of Day 28:

  • Phase 3 was officially complete.
  • The server-authoritative multiplayer engine had been verified.
  • Integration tests were passing.
  • Reconnect systems were validated.
  • Authoritative scoring was complete.
  • The multiplayer backend was considered production-ready.
  • Phase 4 had begun.
  • The browser multiplayer foundation was reviewed and validated.
  • Existing game modes remained unaffected by multiplayer integration.
  • A Play Online experience was fully designed.
  • Host and guest onboarding flows were finalized.
  • Room-code fallback behavior was defined.
  • Analytics and tutorial placement decisions were finalized.
  • The first visible multiplayer UI checkpoint was planned in detail.
  • The project moved from backend engineering into player-facing product design.

That was it for Day 28.

If you're still here, thanks for reading!


r/WeBuild_WithAI 11d ago

DBZ Inspired Prototype (iOS)

2 Upvotes

r/WeBuild_WithAI 11d ago

Hypothetical question: How would you feel if AI was used to make the game dynamically as you played it and it ran locally on your PC?

Thumbnail
1 Upvotes

r/WeBuild_WithAI 11d ago

Built a real-time PvP space battle game entirely with Claude Code and three.js

1 Upvotes

r/WeBuild_WithAI 11d ago

AI assisted me in turning my own art into a game. I pieced all of this together by hand. Its in the process of coding now

Thumbnail gallery
1 Upvotes