Skip to content

feat: guided tutorial for first-time players#215

Merged
Larkooo merged 14 commits intomainfrom
lattice/1774622052
Mar 27, 2026
Merged

feat: guided tutorial for first-time players#215
Larkooo merged 14 commits intomainfrom
lattice/1774622052

Conversation

@Larkooo
Copy link
Copy Markdown
Contributor

@Larkooo Larkooo commented Mar 27, 2026

Summary

Adds a step-by-step interactive tutorial that activates on a player's first practice game. The tutorial walks new players through the core game mechanics with scripted orb pulls and contextual tooltips.

Tutorial Flow

  • Home page: Welcome overlay spotlighting the Practice button
  • 6 scripted pulls: Points → Bomb → Multiplier → Triple Bomb → Health → Points-to-milestone, each followed by an explanation tooltip
  • Milestone/Shop guidance: Cash Out vs Continue choice, ante explanation, shop bits, orb pricing
  • Free play: After the shop tutorial, the player plays freely until game end
  • Game end: Explains Moon Rocks → Glitch Tokens conversion and Reward Mode

Implementation

  • Tutorial state machine (client/src/tutorial/): 35-step state machine with localStorage persistence, React context, and hooks
  • Scripted pulls: forcedOrbId parameter threaded through offline engine → store → actions hook to force specific orbs during tutorial
  • Spotlight overlay: SVG clip-path with evenodd fill rule creates circular (puller) or rounded-rect (buttons) cutouts that pass both visual rendering and pointer events through to the underlying UI
  • Pull blocking: Puller is disabled during tutorial explanation steps, only enabled at designated pull points
  • Overlay suppression: Reward overlay, Level Complete overlay, and Entering Level overlay are suppressed during the scripted tutorial phase

Key design decisions

  • data-tutorial-id attributes on wrapper <div>s (not on Button components directly) so the spotlight targets the full visual element including GradientBorder
  • clip-path: path(evenodd, ...) approach for interactive spotlight steps — creates a pointer-event hole so clicks pass through to the real button underneath
  • Tutorial tooltip styling matches the codebase design system: font-secondary (VCR OSD Mono), raw hex colors from CSS variables, GradientBorder-style card with #0A1A0A background

Test plan

  • First visit: welcome overlay appears on home page, spotlighting Practice button
  • Clicking Practice starts tutorial game, skips reward overlay
  • 6 scripted pulls fire in correct order with explanation tooltips after each
  • Pull button is blocked during explanation steps, enabled during wait-pull steps
  • Bag explanation step spotlights ORBS button, opens bag on click
  • Milestone choice spotlights Continue button, clicking it shows ante explanation
  • Shop: adding first orb shows price increase tooltip immediately
  • After shop exit, "7 Levels" message shows (no Entering Level overlay)
  • Game over (win or lose) shows appropriate tutorial message
  • Returning to home shows Reward Mode explanation
  • Second practice game: no tutorial (localStorage flag persisted)
  • No infinite render loops on game over

🪟 Made with Lattice

Larkooo added 11 commits March 27, 2026 10:04
Implements a step-by-step tutorial that activates on a player's first
practice game. The tutorial guides through 6 scripted orb pulls (points,
bomb, multiplier, triple bomb, health, points-to-milestone), explains
game mechanics at each step with spotlight overlays, walks through the
milestone choice and shop, then lets the player free-play until game end.

- Tutorial state persisted in localStorage (survives reload)
- Scripted pulls via forcedOrbId param threaded through engine/store/actions
- Spotlight overlay with SVG mask cutout, positioned tooltips, and arrows
- data-tutorial-id attributes on key UI elements for targeting
- Reward overlay suppressed during tutorial for direct game entry
- Level-up overlay suppressed during scripted phase
- Post-game messages explain reward mode on return to home

Co-Authored-By: Lattice
The overlay was capturing all pointer events, preventing clicks from
reaching the underlying buttons (practice, puller, bag, continue).

Split the backdrop into 4 dark panels around the spotlight gap for
interactive steps so clicks in the spotlight pass through to the real
DOM elements. Non-interactive steps still use a full-screen backdrop
with SVG mask. Also updated hint text to say "TAP THE HIGHLIGHTED AREA"
for target-only steps.

Co-Authored-By: Lattice
The outer overlay container uses pointer-events: none so the spotlight
gap is clickable, but child backdrop elements were inheriting that and
couldn't receive tap events. Added explicit pointerEvents: "auto" to
all backdrop panels (4-panel split, SVG mask, and full-screen div).

Co-Authored-By: Lattice
Replaced the 4-panel rectangular gap with SVG clip-path donut approach.
clip-path affects both rendering and hit-testing, so clicks inside the
circle pass through to the puller button. Added spotlightShape config
option ("rect" | "circle") to step definitions. The PULL_PROMPT step
now uses a circular cutout with extra padding for a clean look.

Co-Authored-By: Lattice
The data-tutorial-id was on the wrapper div that includes the multiplier
badge, making the bounding rect taller than the actual puller. Moved the
attribute to the Puller component itself so the circular spotlight is
centered precisely on the pull button.

Co-Authored-By: Lattice
The spotlight targeting of the practice button was fragile — the
data-tutorial-id ended up on the inner <button> inside GradientBorder,
and when not found the backdrop blocked all interaction with no hole.

Changed HOME_WELCOME to a centered tap-anywhere overlay with no target.
Tapping dismisses it, then the player clicks practice naturally. The
tutorial activates when they click practice via startTutorial().

Co-Authored-By: Lattice
The data-tutorial-id on Button components ended up on the inner <button>
inside GradientBorder, making the spotlight misaligned and clicks unable
to reach the real element.

Wrapped practice button (desktop + mobile), ORBS button, and CASH OUT
button in plain <div data-tutorial-id="..."> wrappers so the spotlight
covers the full visual element and the clip-path hole lines up with the
actual clickable area.

Restored HOME_WELCOME as an interactive spotlight step pointing at the
practice button.

Co-Authored-By: Lattice
The inner path in the clip-path donut wound the same direction as the
outer rect. With the default nonzero fill rule, both regions counted as
"inside" so no hole appeared. Adding evenodd makes the inner region
alternate to "outside", creating the visible cutout for both circle and
rounded-rect spotlights.

Co-Authored-By: Lattice
Only allow pulls at PULL_PROMPT and WAIT_PULL steps. All other steps
in the scripted phase (overlays, AFTER_PULL animations, explanations)
now block pulling. After FREE_PLAY the restriction is lifted.

Co-Authored-By: Lattice
- Trigger onOrbBought from onBalanceChange when balance drops (user
  tapped + on an orb) instead of waiting for shop confirm. This shows
  the "price increases" tooltip immediately while still in the shop.
- Suppress "Entering Level X" overlay during tutorial scripted phase
  so it doesn't cover the tutorial tooltips.
- handleBuyAndExit now only calls onShopExited (not onOrbBought).

Co-Authored-By: Lattice
The tutorial useEffects had `tutorial` in their dependency arrays.
Since the tutorial context value object is recreated on every state
change, calling onGameEnd (which updates tutorial state) triggered
the effect again, causing an infinite setState loop.

Removed `tutorial` from deps of game-over and pull-animation-complete
effects — they only need to fire on game state changes, not tutorial
state changes.

Co-Authored-By: Lattice
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
glitchbomb Ready Ready Preview Mar 27, 2026 4:02pm
glitchbomb-storybook Ready Ready Preview Mar 27, 2026 4:02pm

Request Review

Shortened pull outcome animation from 2000ms to 1200ms during the
tutorial scripted phase so explanation tooltips appear faster after
each pull. Also reduced tooltip entrance animation delay from 150ms
to 80ms and duration from 300ms to 200ms for snappier feel.

Co-Authored-By: Lattice
- game.tsx: use tutorialRef to read tutorial state inside useLayoutEffect
  instead of accessing tutorial.state directly (avoids adding tutorial
  to deps which would cause re-render loops)
- TutorialOverlay.tsx: add currentConfig.spotlightShape to useEffect deps

Co-Authored-By: Lattice
@Larkooo Larkooo merged commit 962744b into main Mar 27, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant