From faec897d801938bc047bc2775ed95f3c74bec2b0 Mon Sep 17 00:00:00 2001 From: Oliver Rieger Date: Fri, 31 Jul 2026 19:52:31 +0200 Subject: [PATCH] Record the shipping plan and four sound-research todos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discussion-only session, no code. HANDOFF gets a new LATER section holding the decisions: paid $2.99 both stores with no ads, a web demo capped at the end of chapter 1, the CHALLENGE (Hawk-Eye as a free earned continue) and the short-form video campaign — plus what must NOT be built, because selling weapons or adding a meta currency would fight settled design decisions. OPEN gains item 11: the ball machine's squeak, burning zombies, the machine-gun burst and the boss sound set all need a source chosen before implementing. Co-Authored-By: Claude Opus 5 --- HANDOFF.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 4 deletions(-) diff --git a/HANDOFF.md b/HANDOFF.md index a042e32..c36141e 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -5,10 +5,11 @@ everything they specified is shipped, and what still matters from them is record long history, `~/.claude/projects/.../memory/splatter-tennis-history.md` is auto-loaded; for the detail of any individual change, read the git log. -Last updated 2026-07-30, after Oliver's fourth playtest round. **Start with "How to work on this" -and "OPEN — leftovers"** (both just above the CLOSED sections) — the first tells you how his feedback -should be handled, the second is everything known to be outstanding. All four playtest rounds are -closed below them, newest first. **Awaiting his next phone playtest.** +Last updated 2026-07-31. **Start with "How to work on this", "OPEN — leftovers" and "LATER — +shipping it"** (all three just above the CLOSED sections) — the first tells you how Oliver's feedback +should be handled, the second is everything known to be outstanding in the game, the third is the +demo/store/campaign plan, which is decided but entirely unbuilt. All four playtest rounds are closed +below them, newest first. **Awaiting his next phone playtest.** ## What this is SNES-style pseudo-3D tennis (Super Tennis reference) that transitions into a zombie splatter game @@ -468,6 +469,79 @@ Nothing here is broken; these are known gaps and unverified risks. that catches your shots. Recorded so the ideas are not lost, not as a to-do. 10. **`ump_no_deal` does not exist.** Oliver asked for its removal; `ump_no_appeal` was removed as the closest match. Worth one confirmation that no other line is still unwanted. +11. **Four sounds are missing and need RESEARCH first** (find/choose the source before implementing — + every existing sfx is either synthesised in `audio.js` or a wav in `assets/audio/`): + - the **ball machine** while it moves — a squeaking wheel/castor, so the furniture announces + itself. It already telegraphs its shot (`machWind` 0.9 s); this is the *approach* cue. + - **burning zombies** — fire is an epidemic now (`burnSpread`, `burnTime` 3 s), so this is a + looping crackle plus something the body does, and it has to layer without turning a lit-up + wave into noise. + - the **melee gun** — i.e. the machine-gun burst (`mgRate` 12/s during a horde, `mgPickupLen` 8 s + from a tin). At 12 rounds/s a per-pellet sample will machine-gun the mixer, not just the wave. + - **boss sounds** — footfall, wind-up, throw, wound, death. Three designs in `BOSS_ART`; decide + whether they share one set or get one each before recording anything. + +--- + +# LATER — shipping it: demo, stores, campaign + +Decided in discussion 2026-07-31 with Oliver. **None of this is built.** Recorded here so the +decisions survive; the ordering below is roughly the order to do it in. + +**The model: paid, $2.99, no ads.** Both stores. No ad SDK, no consent/CMP flow, no ATT prompt, no +tracking — which keeps the store card at "Data Not Collected", keeps review trivial, and keeps a +zero-dependency project zero-dependency. *Maybe* later: a free build capped at chapter 1 with an IAP +to unlock all chapters. That is a fallback, not the plan — paid→free is a normal move, free→paid is +not, so launch paid. +**Ads are rejected**, with one exception held in reserve: rewarded video on the CHALLENGE (below), +never an interstitial. An interstitial after death would land exactly in the "one more run" gap that +`EATEN_RESTART` exists to protect, and would end sessions rather than annoy. + +1. **The capped web demo.** The public web build stops at the **end of chapter 1** — after the first + chapter boss is beaten (`G.runGames >= 10`, `bossEvery`), on the chapter-2 card, ending on a WIN, + not a wall: "CHAPTER 2 — continue on the App Store." The cut must sit *after* everything a promo + clip promises (transition, first horde, a duel, weapons, the boss), because the web build's whole + job is converting a 15-second clip into "I played it". + Implementation is ~10 lines: a check on the chapter-2 card plus a build flag the store build sets + to skip it. **Build no protection around it** — it is client-side JS on a static host, trivially + bypassable, and nobody who would pay $2.99 will open devtools. DRM here is pure cost. + Consider leaving **desktop uncapped** (`matchMedia('(pointer: coarse)')`, already used for + `autoAssist`): nothing to cannibalise there, and an uncapped desktop build is what gets linked. +2. **Store readiness.** Wrap the PWA (Capacitor/PWABuilder). Unknowns to check *before* committing: + audio behaviour in WKWebView, safe-area (already solved for the browser, may differ in the shell), + and 60 fps canvas under WKWebView at `RES` 4 — see OPEN 1, this is the second place that risk + lands. Costs: a build step in a deliberately build-step-free project, Apple $99/yr, Google $25 + once. Landscape (OPEN 6) probably has to stop being under-maintained before a store review. +3. **The CHALLENGE — ship it FREE.** Tennis already owns the paid-continue mechanic: Hawk-Eye. On + death (`G.mode='eaten'`), the umpire announces a challenge, the replay shows the shambler's foot + over the line, and the call is **overturned** — you resume. The sport supplies the cap for free + (challenges per set), so the limit is diegetic rather than a paywall excuse. + Build it as an **earned** mechanic, not a purchase. It is good design on its own, and it is the + only slot in the game that could ever carry a rewarded video if the model changes. Note it does + change what a run *means* — right now the run summary is the whole game — so it needs a playtest + on feel before it is assumed good. +4. **Short-form video campaign.** The only free channel that reaches people who have never heard of + the game; the algorithm serves cold, so every post is a free lottery ticket. Format: vertical + (portrait is already primary — no letterboxing, unlike most game footage), open mid-rally on what + looks like an ordinary SNES tennis game, reveal the transition at ~3-5 s. Sound matters: the + recorded umpire over splatter is what earns an unmute. Volume over polish — 20-30 clips, one + export cross-posted to TikTok/Reels/Shorts. **No devlog content** (it reaches developers, who do + not buy games). + Clips the game already contains: the transition (the flagship), a boss walking on, the ball boy + calmly mopping blood, a flame ball starting an epidemic across a lined-up wave, parrying a boss's + volley back into him, a horde, the death + run summary. + A capture helper on `window.T` to jump straight into a given beat (the transition timeline is on + `G.transT`) would make clean takes cheap — not yet built. + +**Expectations, so nobody is surprised:** with no marketing, 20-100 units in year one is the honest +central estimate (~$40-210 net, i.e. under Apple's fee at the low end). The monetization model is +worth maybe $200 either way; the video channel is worth ~100x that. Ship paid because it is cheap and +protects the design, not because it will earn. + +**Explicitly NOT to be built** (these fight settled decisions, see the invariants above): +- **selling weapons or tins** — weapons are *only ever won*, in the duel; a shop deletes the duel's + reason to exist and `healPerDuel` with it. +- **a meta-progression currency** — permadeath and the run summary *are* the meta layer. ---