diff --git a/plans/261001-1052-gacha-wish-command/plan.md b/plans/261001-1052-gacha-wish-command/plan.md index 047f0d1..1d0e090 100644 --- a/plans/261001-1052-gacha-wish-command/plan.md +++ b/plans/261001-1052-gacha-wish-command/plan.md @@ -12,7 +12,8 @@ with stars), rendered as a silent MP4 by the existing wheelofnames service. - Renderer lives in `tiennm99/wheelofnames` as `POST /api/gacha`; no new repo or deployment. -- Rarity is user-tagged: `Pizza*5, Pho*4, Rice` (untagged = 3★). +- Rarity is a user prefix: `Pizza, 4* Pho, 3* Rice` (unprefixed = 5★; + switched from the original `Pizza*5` suffix with a 3★ default on 2026-10-01). - Single pull only. - Output MP4 (H.264, no audio) sent via `sendAnimation`. @@ -36,5 +37,5 @@ with stars), rendered as a silent MP4 by the existing wheelofnames service. ## Acceptance - Each rarity renders with the correct meteor/glow colour and star count. -- `/gacha` with no options shows usage; untagged options behave like /random. +- `/gacha` with no options shows usage; every option is equally likely, like /random. - Renderer failure falls back to text; thread IDs forwarded. diff --git a/plans/reports/research-261001-1315-gacha-tier-escalation.md b/plans/reports/research-261001-1315-gacha-tier-escalation.md new file mode 100644 index 0000000..90aab5d --- /dev/null +++ b/plans/reports/research-261001-1315-gacha-tier-escalation.md @@ -0,0 +1,63 @@ +# Research: escalating the gacha wish animation by tier + +Conducted 2026-10-01. Target: `tiennm99/wheelofnames` `src/remotion/GachaComposition.jsx`. + +## Outcome + +Genshin signals rarity mainly through **colour, size, and how much the screen +is taken over**, not through different choreography. Each tier keeps the same +beats (meteor, flash, reveal, star pops), and the higher tier gets more of +everything: a bigger, longer meteor; a halo; more particles; a stronger flash; +and a richer reveal. Our current composition already follows the beats but +scales almost nothing except colour, which is why 3★, 4★, and 5★ feel the same. + +## How the source game escalates + +| Beat | 3★ | 4★ | 5★ | +|---|---|---|---| +| Meteor | Blue, thin trail | Purple, brighter, wider trail | Gold, largest, longest trail | +| Tell before landing | none | none | rainbow-like ring forms around the star ([community report](https://genshin-impact.fandom.com/f/p/4400000000000309937)) | +| Screen | night sky | night sky | gold light floods the screen, cascade of sparkles ([overview](https://img.krmangalam.edu.in/star-base/genshin-impact-5-star-wish-animation-secrets-1764806225)) | +| Reveal | plain item card | character/weapon reveal with streaks | same, plus the strongest glow and the longest build-up | +| Stars | pop in gold, one at a time | same | same; the count itself is the payoff | + +The fandom wiki page for Wish was not reachable (HTTP 402), so the table above +also relies on well-known gameplay behaviour; treat the 4★ "brighter trail" +row as observed convention, not documented spec. + +## Techniques that fit our renderer + +The renderer draws DOM/CSS frames in Chrome headless and encodes H.264. +Measured cost today is about 6.6–6.9 s per 7 s clip, against a 15 s +production timeout, so there is headroom but not unlimited headroom. + +- **Scale the existing layers by tier** (cheapest, biggest effect): meteor head + size, trail length and sample count, spark count, ray opacity, mote count. +- **Halo ring for 5★** on the meteor before landing, drawn as a + `conic-gradient` rainbow ring with a radial mask, matching the in-game tell. +- **Screen flood for 5★**: tint the sky gold as the meteor nears the ground and + make the flash longer and warmer. +- **Camera shake** on impact for 4★ and 5★: decaying `translate` on the whole + frame; this is a standard impact device (Remotion templates ship one, see + [remotion-templates](https://github.com/reactvideoeditor/remotion-templates)). +- **Shockwave rings**: one ring for 3★, two for 4★, three plus a starburst for + 5★. +- **Rank letter emblem** (`B`/`A`/`S` per the user's request) instead of the + label's first character, with a heavier frame and a sheen sweep at 5★. +- **Falling sparkle rain** behind the 5★ reveal ("raining stars"). + +`@remotion/effects` (glow, lightTrail, starburst; from v4.0.464, +[docs](https://www.remotion.dev/docs/effects/api)) is not installed and applies +only to specific Remotion components. Adding it would be a new dependency for +effects we can already draw with gradients, so it is not recommended. + +## Recommendation + +Keep one composition and drive every effect from a per-tier "intensity" table +in `gacha-timeline.js`, so the escalation is data, testable, and tunable. +Re-measure render time after the change; keep it under about 10 s. + +## Unresolved questions + +- None blocking. The exact 4★ visual delta in the source game is convention, + not documented. diff --git a/plans/reports/research-261001-1332-gacha-meteor-gravity.md b/plans/reports/research-261001-1332-gacha-meteor-gravity.md new file mode 100644 index 0000000..a32c102 --- /dev/null +++ b/plans/reports/research-261001-1332-gacha-meteor-gravity.md @@ -0,0 +1,59 @@ +# Research: a realistic gravity fall for the gacha meteor + +Conducted 2026-10-01. Target: `tiennm99/wheelofnames` `src/remotion/gacha-timeline.js` +(`getMeteorState`) and `GachaComposition.jsx`. + +## Outcome + +Users said the fall did not look good ("Cái bay xuống chưa đẹp"). The cause: +the meteor moved along a fixed quadratic Bézier with a quadratic ease-in on +the curve parameter. That is not motion under gravity: it starts almost still, +whips to the end, and its trail was spaced along the curve instead of in time, +so it bunched up early and showed no sense of speed. + +The fix is plain Newtonian projectile motion, which the sources agree is the +right model: constant horizontal speed, vertical speed growing linearly under +gravity, which traces a true parabola +([Wikipedia: projectile motion](https://en.wikipedia.org/wiki/Projectile_motion), +[GameDev.net](https://www.gamedev.net/forums/topic/629786-projectile-motion-parabola/4970539/)). + +## Formula + +With launch point `P0`, impact point `P1`, fall duration `T`, and a chosen +launch slope `k` (vertical speed as a fraction of horizontal speed): + +```text +vx = (x1 - x0) / T +vy0 = |vx| * k k = -0.3: launches slightly upward +g = 2 * (y1 - y0 - vy0 * T) / T² solved so it lands exactly at P1 +x(t) = x0 + vx * t +y(t) = y0 + vy0 * t + ½ g t² +vy(t) = vy0 + g t +``` + +Solving `g` from the endpoints keeps the impact point and timing fixed, so +the flash and reveal choreography is unchanged. With `k = -0.3` the meteor +climbs at about 17°, bends over, and dives at about 54° while speeding up. + +## Supporting techniques + +- **Motion streak sampled in time:** the trail draws the meteor's own past + positions every 16 ms, so its length grows with speed, which is how motion + blur reads ([Wikipedia: motion blur](https://en.wikipedia.org/wiki/Motion_blur_(media))). +- **Velocity-aligned stretch:** the head is rotated to `atan2(vy, vx)` and + stretched along it while thinning across it to keep its area, the standard + squash-and-stretch for fast objects + ([Programmatic squash and stretch](http://www.alexgalbraith.nz/2019/04/05/programmatic-squash-and-stretch/)). +- **Spark physics:** each spark inherits part of the meteor's velocity plus a + random kick, then falls under its own gravity while fading. + +## Verification + +A time-lapse of rendered frames shows a clear parabolic arc with gaps that +widen as the meteor accelerates. Tests check constant horizontal speed, +constant vertical acceleration, the exact landing point, and the climb-to-dive +angles. Render time is unchanged (about 9 s for 5★, 7 s for 3★/4★). + +## Unresolved questions + +- None.