The Core Game Loop
The loop is deliberately split across four time scales. Players receive clear feedback every second, every few minutes and every run, while the ESP32 can keep high-frequency rendering separate from low-frequency persistence.
0–2 seconds: one touch transaction
- Pointer down creates one owner and records position, time and starting page.
- Movement below 12 px can still become a tap or hold. Crossing the threshold latches cancellation permanently, so returning to the origin cannot create a tap on release.
- The hold enters stages at 0.65 / 1.2 / 1.9 seconds; release converts elapsed time to
chargeRatio. GameEngine.coreAction()resolves combo, lucky timing, heat, equipment and permanent Gifts at one commit point.- State commits first. Particles, callouts, audio and frame FX follow as presentation; ambient or device sequences may suppress them without rolling back the economy.
const chargeMultiplier = 1 + chargeRatio * 4 * (turbo ? 1.35 : 1)
const gain = floor(
tapPower
* comboMultiplier
* heatMultiplier
* luckyMultiplier
* chargeMultiplier
* permanentMultiplier
* badgeMultiplier
)2–60 seconds: rhythm and risk
- Combo: continue within 1.4 seconds, up to 20 stacks at +5% each.
- Lucky beat: hit within ±10° of the sync cursor for ×3, or ×4 after the Gift.
- Heat: taps and charges build heat. High heat strengthens taps, but maximum heat triggers three seconds of protection.
- Cooling: base cooling is 2.4 heat/s; FAN adds 40%, while ICE PACK removes another 8 on lucky hits.
- Three-stage burst: after release, v7 continues with 1.8 / 3.0 / 4.5 seconds of automatic beats. Ambient display, launch and device sequences cancel it immediately.
The player chooses between maintaining combo, waiting for the lucky angle, charging and controlling heat instead of simply tapping as fast as possible.
1–10 minutes: automation and TEAM
Sparks buy six Maker families. Each has a base rate and an identity rule. Makers occupy three orbits; close cross-orbit angles form TEAM links. Every valid link adds 15%, with at most three links counted per Maker.
Dragging the SHOP ring updates a render-only preview. A stable release commits phase, task progress, achievements and fx_grow exactly once. Leaving the capture ring, crossing the center, cancellation or page navigation discards the preview.
30+ minutes: launch and permanent growth
Once lifetime Sparks reach the threshold, STAR exposes the launch yield:
badges = floor(sqrt(lifetimeSparks / 1_000_000))Launch requires two independent confirmations inside ten seconds. The second confirmation:
- locks input and plays the ten-frame
fx_loop; - stores a new star permanently in the archive;
- grants Badges, while each historical Badge adds a permanent 5% global multiplier;
- resets run Sparks, tap power and Makers while preserving Gifts, Badges and history;
- returns to SEED after 1.2 seconds and highlights the new archived star for 2.6 seconds.
Offline loop
The web version uses the saved wall-clock timestamp; hardware uses the PCF85063 RTC. Rewards are granted only when both old and current clocks are trustworthy:
credited = min(realElapsed, 4h + toolBattery2h + giftBattery2h)
offlineGain = CPS × credited × 60%An untrusted RTC only updates the timestamp. This conservative rule keeps player progress, test snapshots and power-loss recovery auditable.
Why it fits a round display
A round screen cannot keep a long purchase list visible. The system unfolds through “center action → circular entry → single-focus card.” The player only needs to understand one primary object at a time; complexity grows through long-term relationships, not by filling one screen with controls.
