hayao 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/design/00-process/README.md +49 -0
- package/design/00-process/composition.md +148 -0
- package/design/00-process/core-loop.md +146 -0
- package/design/00-process/intent-to-brief.md +128 -0
- package/design/00-process/pillars.md +139 -0
- package/design/00-process/refine-and-handoff.md +156 -0
- package/design/00-process/the-twist.md +108 -0
- package/design/10-anchors/README.md +99 -0
- package/design/10-anchors/age-of-empires.md +103 -0
- package/design/10-anchors/baba-is-you.md +127 -0
- package/design/10-anchors/balatro.md +132 -0
- package/design/10-anchors/celeste.md +136 -0
- package/design/10-anchors/civilization.md +101 -0
- package/design/10-anchors/dead-cells.md +125 -0
- package/design/10-anchors/factorio.md +100 -0
- package/design/10-anchors/hades.md +127 -0
- package/design/10-anchors/into-the-breach.md +125 -0
- package/design/10-anchors/it-takes-two.md +104 -0
- package/design/10-anchors/loop-hero.md +131 -0
- package/design/10-anchors/nuclear-throne.md +130 -0
- package/design/10-anchors/outer-wilds.md +107 -0
- package/design/10-anchors/overcooked.md +102 -0
- package/design/10-anchors/peggle.md +133 -0
- package/design/10-anchors/reigns.md +99 -0
- package/design/10-anchors/return-of-the-obra-dinn.md +108 -0
- package/design/10-anchors/rimworld.md +101 -0
- package/design/10-anchors/shadow-of-mordor.md +106 -0
- package/design/10-anchors/slay-the-spire.md +127 -0
- package/design/10-anchors/starcraft.md +98 -0
- package/design/10-anchors/stardew-valley.md +103 -0
- package/design/10-anchors/tetris.md +122 -0
- package/design/10-anchors/vampire-survivors.md +122 -0
- package/design/20-genres/README.md +62 -0
- package/design/20-genres/action-adventure.md +126 -0
- package/design/20-genres/auto-battler.md +121 -0
- package/design/20-genres/bullet-hell.md +123 -0
- package/design/20-genres/city-builder.md +124 -0
- package/design/20-genres/coop-chaos.md +124 -0
- package/design/20-genres/deckbuilder.md +122 -0
- package/design/20-genres/exploration.md +131 -0
- package/design/20-genres/farming-sim.md +122 -0
- package/design/20-genres/grid-puzzle.md +126 -0
- package/design/20-genres/horde-survival.md +128 -0
- package/design/20-genres/incremental.md +120 -0
- package/design/20-genres/match3.md +120 -0
- package/design/20-genres/metroidvania.md +132 -0
- package/design/20-genres/narrative-decisions.md +122 -0
- package/design/20-genres/physics-arcade.md +124 -0
- package/design/20-genres/precision-platformer.md +127 -0
- package/design/20-genres/racing.md +126 -0
- package/design/20-genres/rhythm.md +125 -0
- package/design/20-genres/roguelike.md +122 -0
- package/design/20-genres/rts.md +169 -0
- package/design/20-genres/stealth.md +125 -0
- package/design/20-genres/survival-horror.md +124 -0
- package/design/20-genres/tactics.md +123 -0
- package/design/20-genres/tower-defense.md +120 -0
- package/design/30-systems/README.md +69 -0
- package/design/30-systems/accessibility.md +110 -0
- package/design/30-systems/boss-design.md +126 -0
- package/design/30-systems/build-diversity.md +120 -0
- package/design/30-systems/collectibles.md +108 -0
- package/design/30-systems/combat-model.md +113 -0
- package/design/30-systems/coop-and-competition.md +118 -0
- package/design/30-systems/counter-systems.md +115 -0
- package/design/30-systems/crafting.md +115 -0
- package/design/30-systems/difficulty-and-dda.md +114 -0
- package/design/30-systems/economy.md +117 -0
- package/design/30-systems/emergent-systems.md +114 -0
- package/design/30-systems/encounter-design.md +107 -0
- package/design/30-systems/enemy-ai.md +121 -0
- package/design/30-systems/enemy-archetypes.md +117 -0
- package/design/30-systems/faction-asymmetry.md +144 -0
- package/design/30-systems/grace.md +124 -0
- package/design/30-systems/mastery-curve.md +116 -0
- package/design/30-systems/meta-progression.md +114 -0
- package/design/30-systems/onboarding.md +115 -0
- package/design/30-systems/procgen-design.md +118 -0
- package/design/30-systems/progression.md +120 -0
- package/design/30-systems/resource-loops.md +112 -0
- package/design/30-systems/reward-schedules.md +124 -0
- package/design/30-systems/save-and-checkpoint.md +113 -0
- package/design/30-systems/session-structure.md +113 -0
- package/design/30-systems/skill-trees.md +111 -0
- package/design/30-systems/status-effects.md +111 -0
- package/design/30-systems/tech-tree.md +112 -0
- package/design/30-systems/telegraphs.md +106 -0
- package/design/30-systems/unit-rosters.md +123 -0
- package/design/40-worldbuilding/README.md +49 -0
- package/design/40-worldbuilding/aesthetic-direction.md +155 -0
- package/design/40-worldbuilding/faction-identity.md +136 -0
- package/design/40-worldbuilding/naming-and-tone.md +130 -0
- package/design/40-worldbuilding/narrative-delivery.md +129 -0
- package/design/40-worldbuilding/theme-vectors.md +134 -0
- package/design/40-worldbuilding/worldbuilding-scaffold.md +132 -0
- package/design/50-patterns/README.md +54 -0
- package/design/50-patterns/anti-frustration.md +121 -0
- package/design/50-patterns/emergence.md +121 -0
- package/design/50-patterns/feedback-loops.md +121 -0
- package/design/50-patterns/juice-choreography.md +124 -0
- package/design/50-patterns/mastery-and-flow.md +121 -0
- package/design/50-patterns/pacing-and-tension.md +120 -0
- package/design/50-patterns/readability.md +121 -0
- package/design/50-patterns/risk-reward.md +120 -0
- package/design/CONTRIBUTING.md +183 -0
- package/design/INDEX.md +133 -0
- package/design/README.md +86 -0
- package/design/_TEMPLATE.md +69 -0
- package/design/index.json +2720 -0
- package/dist/anim/blend.d.ts +68 -0
- package/dist/anim/clip.d.ts +87 -0
- package/dist/anim/ik.d.ts +40 -0
- package/dist/anim/skeleton.d.ts +64 -0
- package/dist/hayao.global.js +12 -12
- package/dist/index.d.ts +11 -1
- package/dist/index.js +1683 -516
- package/dist/index.js.map +4 -4
- package/dist/index.min.js +12 -12
- package/dist/render/canvas2d-core.d.ts +4 -0
- package/dist/render/commands.d.ts +19 -0
- package/dist/render/lightRun.d.ts +35 -0
- package/dist/render/svgString.d.ts +8 -3
- package/dist/scene/clipPlayer.d.ts +58 -0
- package/dist/scene/ikTarget.d.ts +25 -0
- package/dist/scene/light.d.ts +80 -0
- package/dist/scene/shadow2d.d.ts +25 -0
- package/dist/scene/skeletonDebug.d.ts +28 -0
- package/dist/verify/gates.d.ts +25 -0
- package/docs/API.md +66 -8
- package/docs/CONVENTIONS.md +56 -0
- package/package.json +2 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: pattern-emergence
|
|
3
|
+
title: Emergence
|
|
4
|
+
kind: pattern
|
|
5
|
+
tags: [emergence, second-order, systemic, interaction, depth, combinatorics, rules, synergy]
|
|
6
|
+
summary: Depth from few pieces — design rules that interact, not content that stacks, so the game generates situations you never authored.
|
|
7
|
+
use-when: You want combinatorial depth without infinite content; deciding between more rules or more interactions between rules.
|
|
8
|
+
composes-with: [pattern-feedback-loops, pattern-risk-reward, system-emergent-systems, system-build-diversity]
|
|
9
|
+
verify-with: docs/FUN.md#12-·-turn-based-tactics-into-the-breach-like
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Emergence
|
|
13
|
+
|
|
14
|
+
**What it is.** **Emergent** depth comes from a small set of rules that *interact*,
|
|
15
|
+
producing situations the designer never explicitly authored. The opposite of
|
|
16
|
+
content-stacking (a thousand bespoke levels) is second-order design: a dozen verbs
|
|
17
|
+
that combine into millions of states. Baba Is You has a handful of word-rules;
|
|
18
|
+
Into the Breach has push, damage, and terrain — the *combinations* are the game.
|
|
19
|
+
|
|
20
|
+
**Player fantasy.** *"I did something the designers didn't plan."* The improvised
|
|
21
|
+
solution, the synergy you discovered, the story only your run could tell. Ownership
|
|
22
|
+
of the *how*, not just the outcome.
|
|
23
|
+
|
|
24
|
+
## Why it works
|
|
25
|
+
|
|
26
|
+
- **Few pieces, deep space.** N interacting rules give ~N² interactions and far more
|
|
27
|
+
states — depth scales combinatorially while your content budget stays flat. This
|
|
28
|
+
is how a tiny game reads as vast.
|
|
29
|
+
- **Discovery is the reward.** An interaction *you* found feels earned in a way a
|
|
30
|
+
handed-to-you unlock never does; it's the [[pattern-mastery-and-flow]] ceiling
|
|
31
|
+
with no assets attached.
|
|
32
|
+
- **Systemic story beats scripted story** ([[system-emergent-systems]]) — the
|
|
33
|
+
nemesis who killed you twice and now taunts you is more memorable than any cutscene
|
|
34
|
+
because *you* co-authored it.
|
|
35
|
+
|
|
36
|
+
## Levers
|
|
37
|
+
|
|
38
|
+
| Lever | Effect | Example |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| **Rule orthogonality** | More rules combine cleanly | Push, fire, and water are independent → they interact |
|
|
41
|
+
| **Shared state** | Systems that read each other | Water conducts electricity *and* extinguishes fire |
|
|
42
|
+
| **Verb reuse** | One verb, many contexts | "Push" affects enemies, allies, terrain alike (ItB) |
|
|
43
|
+
| **Consistency** | Interactions are predictable | Same rule everywhere; no exceptions to memorise ([[pattern-readability]]) |
|
|
44
|
+
| **Legibility** | Players can *see* the interaction coming | Perfect-information telegraphs (FUN.md §12) |
|
|
45
|
+
| **Feedback loops** | Interactions cascade | One rule feeds another ([[pattern-feedback-loops]]) |
|
|
46
|
+
|
|
47
|
+
## Applied across genres
|
|
48
|
+
|
|
49
|
+
| Genre | The interacting pieces | The emergence |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| **Rule-puzzle** ([[anchor-baba-is-you]]) | Word-rules you rewrite | Break "wall is stop" and the whole board reinterprets |
|
|
52
|
+
| **Tactics** ([[anchor-into-the-breach]], [[genre-tactics]]) | Push · damage · terrain · fire | A shove that turns an enemy's attack onto its ally |
|
|
53
|
+
| **Immersive-sim / exploration** ([[genre-exploration]]) | Systemic verbs (fire, water, gravity) | The unintended path through a level |
|
|
54
|
+
| **Deckbuilder** ([[genre-deckbuilder]], [[anchor-balatro]]) | Cards/jokers that read each other | The synergy engine you drafted into existence |
|
|
55
|
+
| **Colony / sim** ([[anchor-rimworld]]) | Needs · relationships · events | The AI director authoring drama from rule collisions |
|
|
56
|
+
| **Systemic memory** ([[anchor-shadow-of-mordor]]) | Rivals with persistent state | The nemesis arc no writer scripted |
|
|
57
|
+
| **Auto-battler** ([[genre-auto-battler]]) | Synergies + positioning | The comp that only works because two traits overlap |
|
|
58
|
+
|
|
59
|
+
## Overdone when…
|
|
60
|
+
|
|
61
|
+
- **Emergent chaos, not depth.** Interactions so tangled the player can't predict
|
|
62
|
+
them — that's noise, not systemic play. Legibility is the price of emergence
|
|
63
|
+
([[pattern-readability]]): Into the Breach shows you *exactly* what every
|
|
64
|
+
interaction resolves to (FUN.md §12).
|
|
65
|
+
- **Degenerate dominant combo.** One interaction is so strong it eats the space —
|
|
66
|
+
the emergent tree collapses to a single branch ([[system-build-diversity]] dead).
|
|
67
|
+
- **Unfair emergence.** A rule collision that softlocks or one-shots the player
|
|
68
|
+
through no readable cause. Emergence must stay *fair*: the losing state should
|
|
69
|
+
have been foreseeable.
|
|
70
|
+
- **Second-order for its own sake.** Interactions no player will ever hit aren't
|
|
71
|
+
depth, they're untested edge cases. Depth is the *reachable* combination space.
|
|
72
|
+
- **Inconsistent rules.** An interaction that fires here but not there ("fire spreads
|
|
73
|
+
on grass, except this grass") breaks the mental model emergence depends on — the
|
|
74
|
+
player stops predicting and starts guessing. One rule, everywhere, no exceptions.
|
|
75
|
+
|
|
76
|
+
## Verify / feel-gate link
|
|
77
|
+
|
|
78
|
+
Emergence is where **perfect honesty** and **pure-state bots** earn their keep:
|
|
79
|
+
|
|
80
|
+
- **Perfect information / intent honesty (FUN.md §12).** For emergent tactics, what
|
|
81
|
+
is shown must be exactly what resolves — store telegraphs as *directions* so a
|
|
82
|
+
push *rewrites* the outcome, and audit that the resolved state matches the shown
|
|
83
|
+
one. An interaction the player can't foresee is a bug.
|
|
84
|
+
- **Mechanic-in-isolation proofs (FUN.md §12).** Prove each verb (push, bump,
|
|
85
|
+
redirect) alone, *then* trust the combinations — you can't unit-test N² states,
|
|
86
|
+
so you test the N rules and the pure sim guarantees the rest.
|
|
87
|
+
- **Clone-and-score bots (FUN.md law 7).** Plain-JSON `world.state` lets a 1-ply
|
|
88
|
+
greedy bot explore the interaction space — it finds the degenerate combo before a
|
|
89
|
+
player does.
|
|
90
|
+
- **Determinism (law 6/7).** Emergent cascades must be reproducible from the seed or
|
|
91
|
+
the systemic story can't be replayed or debugged.
|
|
92
|
+
|
|
93
|
+
## Worked micro-example
|
|
94
|
+
|
|
95
|
+
*"A tiny tactics game that feels vast on a four-verb budget."* Don't author a hundred
|
|
96
|
+
bespoke enemies — author four **orthogonal** verbs (push, damage, fire-spread,
|
|
97
|
+
water-conduct) and one **shared state** (tiles carry fire/water). The depth is in the
|
|
98
|
+
collisions: shove an enemy into water to douse a fire, or into fire to burn it, or
|
|
99
|
+
into *another enemy* to turn its telegraphed attack onto its ally. Nobody scripted
|
|
100
|
+
"redirect a spider's web onto the tank" — the rules produced it. Keep it *fair* with
|
|
101
|
+
legibility: show exactly what each interaction resolves to before the player commits
|
|
102
|
+
([[pattern-readability]], FUN.md §12). Prove the verbs in isolation, then trust the
|
|
103
|
+
N² space; run a greedy clone-bot to surface the degenerate combo before a player does.
|
|
104
|
+
|
|
105
|
+
## Composes with
|
|
106
|
+
|
|
107
|
+
- [[system-emergent-systems]] — this pattern is the *principle*; that system is the
|
|
108
|
+
concrete nemesis/reputation/relationship machinery. Read them together.
|
|
109
|
+
- [[pattern-feedback-loops]] — the loops *between* interacting rules are what make
|
|
110
|
+
emergence cascade instead of fizzle.
|
|
111
|
+
- [[system-build-diversity]] — emergence is only alive while many combinations stay
|
|
112
|
+
viable; a dominant combo kills it.
|
|
113
|
+
- [[pattern-risk-reward]] — the best emergent moments are risky improvisations that
|
|
114
|
+
paid off.
|
|
115
|
+
|
|
116
|
+
## See also
|
|
117
|
+
|
|
118
|
+
- [`docs/FUN.md`](../../docs/FUN.md) §12 & law 7 — perfect-information honesty and
|
|
119
|
+
pure-state bots, the proofs that keep emergence *fair* and *explorable*.
|
|
120
|
+
- [[anchor-baba-is-you]] · [[anchor-into-the-breach]] — the two clearest "the
|
|
121
|
+
mechanic IS the content" anchors.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: pattern-feedback-loops
|
|
3
|
+
title: Feedback Loops
|
|
4
|
+
kind: pattern
|
|
5
|
+
tags: [feedback, snowball, comeback, runaway, balance, positive-loop, negative-loop, catch-up]
|
|
6
|
+
summary: Positive loops snowball, negative loops correct — design which one dominates so leads stay tense, not decided.
|
|
7
|
+
use-when: A lead is being built (economy, kills, board control) and you must decide whether it should compound or self-limit.
|
|
8
|
+
composes-with: [pattern-risk-reward, pattern-pacing-and-tension, system-economy, system-difficulty-and-dda]
|
|
9
|
+
verify-with: docs/FUN.md#part-1-—-universal-laws
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Feedback Loops
|
|
13
|
+
|
|
14
|
+
**What it is.** A **feedback loop** feeds a system's output back into its own
|
|
15
|
+
input. *Positive* loops amplify (a lead makes the next lead easier — a snowball);
|
|
16
|
+
*negative* loops dampen (falling behind makes catching up easier — a rubber band).
|
|
17
|
+
Every game with state has both; the design question is *which one dominates, and
|
|
18
|
+
when*.
|
|
19
|
+
|
|
20
|
+
**Why it's fun.** A pure snowball decides the match at minute two and the rest is
|
|
21
|
+
a formality. A pure rubber band erases skill — why play well if the game hands it
|
|
22
|
+
back? The fun lives in the **tension between them**: a lead that *matters* (so
|
|
23
|
+
building it is exciting) but is *never safe* (so defending it stays tense). The
|
|
24
|
+
[[system-mastery-curve]] skill-delta only reads as fun when a good lead is real
|
|
25
|
+
and a comeback is possible.
|
|
26
|
+
|
|
27
|
+
## Why it works
|
|
28
|
+
|
|
29
|
+
- **A lead you can lose is a lead worth chasing.** If the snowball is uncatchable,
|
|
30
|
+
the loser stops trying and the winner stops sweating — both channels of tension
|
|
31
|
+
die at once.
|
|
32
|
+
- **Loops are the engine of [[pattern-pacing-and-tension]].** Positive loops build
|
|
33
|
+
the peak; negative loops manufacture the valley (the comeback beat) without the
|
|
34
|
+
designer hand-scripting it.
|
|
35
|
+
- **Runaway is a *bug you can prove*.** FUN.md law 2 (skill-delta) has a dark twin:
|
|
36
|
+
if the *winning* strategy's margin grows without bound across a session, a
|
|
37
|
+
bot-vs-bot sim shows the game deciding itself. Assert the lead is bounded, or
|
|
38
|
+
that a trailing bot's win-rate stays > 0.
|
|
39
|
+
|
|
40
|
+
## Levers
|
|
41
|
+
|
|
42
|
+
| Lever | Turns the loop… | Example |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| **Loop gain** (how much output re-feeds input) | Steeper positive → faster snowball | Kill → gold → item → more kills (MOBA) |
|
|
45
|
+
| **Diminishing returns** | Caps a positive loop | Each territory worth less; XP curve inflates |
|
|
46
|
+
| **Catch-up faucet** | Adds a negative loop | Last place gets the blue shell; comeback mechanic in fighting games |
|
|
47
|
+
| **Loss forgiveness** | Softens the *negative* of falling behind | Bankruptcy protection; mercy income floor |
|
|
48
|
+
| **Tempo of payout** | *When* the lead converts | Bank-it-now vs compound-later ([[pattern-risk-reward]]) |
|
|
49
|
+
| **Information** | Whether players *see* the loop | An exposed "+N" lets players fight the snowball ([[pattern-readability]]) |
|
|
50
|
+
|
|
51
|
+
## Applied across genres
|
|
52
|
+
|
|
53
|
+
| Genre | Positive loop (snowball) | Negative loop (comeback) |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| **RTS** ([[genre-rts]]) | Eco lead → more army → more map → more eco | Defender's advantage; cheaper tech when behind |
|
|
56
|
+
| **4X / city** ([[anchor-civilization]], [[genre-city-builder]]) | Cities fund cities; the classic runaway leader | War-weariness, unhappiness, upkeep scaling |
|
|
57
|
+
| **Roguelite** ([[system-meta-progression]]) | Build synergy compounds mid-run | Death resets the run; meta-unlocks aid the *next* attempt, not this lead |
|
|
58
|
+
| **Deckbuilder** ([[genre-deckbuilder]]) | An engine deck draws into itself | Deck bloat; scaling enemy damage punishes stalling |
|
|
59
|
+
| **Horde survival** ([[genre-horde-survival]]) | Build growth is multiplicative | Spawn pressure is *superlinear* (FUN.md §6) — the tide is the negative loop |
|
|
60
|
+
| **Racing** ([[genre-racing]]) | Clean line → speed → gap | Rubber-band AI; slipstream helps the trailer |
|
|
61
|
+
| **Incremental** ([[genre-incremental]]) | Production buys production | Flat payback ratio (~15–25s) caps runaway (FUN.md §14) |
|
|
62
|
+
|
|
63
|
+
## Overdone when…
|
|
64
|
+
|
|
65
|
+
- **The snowball is uncatchable** — the leader wins on turn 3, the game plays out
|
|
66
|
+
a decided result. Add diminishing returns or a comeback faucet.
|
|
67
|
+
- **The rubber band is visible and cheap** — players *see* the game handing back
|
|
68
|
+
their lead and stop caring. Comeback should widen the *chance*, not erase the
|
|
69
|
+
*gap* (the trailer gets a shot, not a gift).
|
|
70
|
+
- **Catch-up punishes winning** — if leading is strictly bad (everyone sandbags to
|
|
71
|
+
avoid the target), the loop inverted. The lead must stay *desirable*.
|
|
72
|
+
- **Two positive loops with no damper** — economy AND military both compound with
|
|
73
|
+
nothing pulling back; the match resolves before skill can express.
|
|
74
|
+
- **A hidden loop** — the snowball is real but the player can't *see* it building, so
|
|
75
|
+
they can't fight it ([[pattern-readability]]). An exposed lead (the live "+N", the
|
|
76
|
+
score bar) turns a runaway from a fait accompli into a target.
|
|
77
|
+
|
|
78
|
+
## Verify / feel-gate link
|
|
79
|
+
|
|
80
|
+
Feedback runaway is a **skill-delta pathology** (FUN.md law 2): run the intended
|
|
81
|
+
line *and* a trailing/null line and assert the trailing side keeps a non-zero
|
|
82
|
+
win-rate across a session — a lead that grows unboundedly is the bot proving the
|
|
83
|
+
game decides itself.
|
|
84
|
+
|
|
85
|
+
- **Bounded-lead assert.** Sim two bots; assert the leader's margin stops growing
|
|
86
|
+
(or the trailer's win-rate stays > 0) — the negative loop is doing its job.
|
|
87
|
+
- **Economy pacing.** For incremental/economy loops, the flat payback-ratio window
|
|
88
|
+
(FUN.md §14, [[system-economy]]) *is* the runaway gate — rising paybacks are an
|
|
89
|
+
unchecked positive loop strangling the late game.
|
|
90
|
+
- **Determinism rail.** All loop randomness (catch-up rolls, blue-shell draws)
|
|
91
|
+
through `world.rng` (FUN.md law 7) or the balance sim can't reproduce the runaway.
|
|
92
|
+
|
|
93
|
+
## Worked micro-example
|
|
94
|
+
|
|
95
|
+
*"An RTS that never feels decided at minute two."* The core positive loop is eco →
|
|
96
|
+
army → map → eco. Left ungated it's a hard snowball. Add three dampers: (1)
|
|
97
|
+
**diminishing returns** — each expansion costs more to defend than the last; (2) a
|
|
98
|
+
**defender's-advantage** negative loop — losing ground makes your remaining ground
|
|
99
|
+
cheaper to hold; (3) an **information** lever — expose the score so the trailer can
|
|
100
|
+
*aim* a comeback ([[pattern-readability]]). Now the lead is real (building it is the
|
|
101
|
+
game) but never safe (defending it is the *other* game). Prove it: two bots, assert
|
|
102
|
+
the leader's margin stops compounding and the trailer keeps a non-zero win-rate.
|
|
103
|
+
|
|
104
|
+
## Composes with
|
|
105
|
+
|
|
106
|
+
- [[pattern-risk-reward]] — *when* to bank a lead vs compound it is a risk decision
|
|
107
|
+
that rides on the loop's gain.
|
|
108
|
+
- [[pattern-pacing-and-tension]] — loops *are* the mechanism that makes peaks and
|
|
109
|
+
valleys emerge instead of being scripted.
|
|
110
|
+
- [[system-economy]] — faucets/sinks are the most common positive/negative loop pair.
|
|
111
|
+
- [[system-difficulty-and-dda]] — dynamic difficulty is a deliberately-added
|
|
112
|
+
negative loop; tune it so it corrects without erasing skill.
|
|
113
|
+
|
|
114
|
+
## See also
|
|
115
|
+
|
|
116
|
+
- [`docs/FUN.md`](../../docs/FUN.md) laws 2 & 7 — skill-delta and pure-state bots,
|
|
117
|
+
the tools that turn "does it snowball?" into an assertion.
|
|
118
|
+
- [[anchor-civilization]] — the "one more turn" snowball-vs-comeback layering, done
|
|
119
|
+
as a whole game.
|
|
120
|
+
- [[genre-incremental]] — the whole genre *is* a positive loop; its flat payback
|
|
121
|
+
window is the cleanest example of a damper holding runaway in check.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: pattern-juice-choreography
|
|
3
|
+
title: Juice as Choreography
|
|
4
|
+
kind: pattern
|
|
5
|
+
tags: [juice, feel, feedback, choreography, particles, shake, cosmetic, two-senses, game-feel]
|
|
6
|
+
summary: The sim resolves instantly and returns a choreography script; the view replays it — every event answers on ≥2 senses.
|
|
7
|
+
use-when: Wiring feedback (impact, pickup, death) or deciding what belongs in the sim vs the view.
|
|
8
|
+
composes-with: [pattern-readability, pattern-anti-frustration, pattern-pacing-and-tension, system-combat-model]
|
|
9
|
+
verify-with: docs/JUICE.md#part-3-—-make-the-feel-checkable-channel-4-gates
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Juice as Choreography
|
|
13
|
+
|
|
14
|
+
**What it is.** Feel is not decoration sprinkled on a sim — it's a **choreography**
|
|
15
|
+
the sim *authors* and the view *performs*. The sim resolves an event instantly and
|
|
16
|
+
returns a script (what happened, when); the view replays it as particles, shake,
|
|
17
|
+
pops, and sound. FUN.md law 6, the **cosmetic-view rule**: views must be deletable
|
|
18
|
+
without changing a single sim bit. Juice is loud *and* free of gameplay risk because
|
|
19
|
+
it never touches the hash.
|
|
20
|
+
|
|
21
|
+
**Player fantasy.** *"That hit felt like it mattered."* Weight, punch, satisfaction —
|
|
22
|
+
the difference between clicking a spreadsheet and landing a blow. The game answering
|
|
23
|
+
your input like it *heard* you.
|
|
24
|
+
|
|
25
|
+
## Why it works
|
|
26
|
+
|
|
27
|
+
- **The 2-senses feedback contract.** Every meaningful event answers on **≥ 2
|
|
28
|
+
senses** within the frame — sfx + particles, or sfx + flash + shake. One channel
|
|
29
|
+
reads as cheap; two reads as *professional* (JUICE.md Part 2). This is the single
|
|
30
|
+
highest-leverage feel rule.
|
|
31
|
+
- **Choreography-not-state keeps determinism sacred.** Because the view reads sim
|
|
32
|
+
*events*, not state it feeds back, a replay reproduces the exact same show and
|
|
33
|
+
deleting the whole view changes not one game bit (FUN.md law 6). You can lean all
|
|
34
|
+
the way into juice at zero risk to the proofs.
|
|
35
|
+
- **Timing is sim time.** Impact, beat, cascade timing is `world.time` / the fixed
|
|
36
|
+
`dt`, never wall-clock — so the choreography is reproducible and the hash holds
|
|
37
|
+
(JUICE.md Part 1).
|
|
38
|
+
|
|
39
|
+
## Levers
|
|
40
|
+
|
|
41
|
+
| Lever | The Hayao primitive | Envelope (JUICE.md Part 2) |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| **Screen shake** | `Shaker` (camera's parent) | land ≈ 0.12, death ≈ 0.5; quadratic falloff, decay ≈ 3/s |
|
|
44
|
+
| **Hit-stop** | freeze frames on impact | sells weight; > ~12 frames reads as a hitch |
|
|
45
|
+
| **Impact particles** | `Particles` + `PARTICLE_PRESETS` | answer an event, life 0.2–0.6s, then vanish |
|
|
46
|
+
| **Pop numbers / pickups** | `FloatingText` + `FLOAT_PRESETS` | one pop per event; don't stack to soup |
|
|
47
|
+
| **Atmosphere** | `AmbientField` + `AMBIENT_PRESETS` | *persistent* field (snow/ash), not a burst stream |
|
|
48
|
+
| **Depth** | `ParallaxLayer` | 0 = far/pinned, 1 = foreground |
|
|
49
|
+
| **Procedural SFX** | `audio.tone/blip/play/success` | pitch-rising combo; the second sense, cheaply |
|
|
50
|
+
|
|
51
|
+
*(Grep [`docs/API.md`](../../docs/API.md) before citing — all of the above are real;
|
|
52
|
+
[`examples/updrift`](../../examples/updrift) wires every one and passes all four feel
|
|
53
|
+
gates.)*
|
|
54
|
+
|
|
55
|
+
## Applied across genres
|
|
56
|
+
|
|
57
|
+
| Genre | The signature choreography |
|
|
58
|
+
|---|---|
|
|
59
|
+
| **Physics arcade** ([[genre-physics-arcade]], [[anchor-peggle]]) | Pitch-rising ricochet chain, big burst on multipliers — the juice *is* the product |
|
|
60
|
+
| **Action-adventure** ([[genre-action-adventure]]) | Hit-stop + flash + i-frame shimmer sell the blow (FUN.md §4) |
|
|
61
|
+
| **Horde survival** ([[genre-horde-survival]]) | Screen full of pops on a level-up; the "number goes up" feast |
|
|
62
|
+
| **Match-3** ([[genre-match3]]) | The purest law 6 — the deterministic sim returns the cascade *script*, the view animates it (FUN.md §13) |
|
|
63
|
+
| **Deckbuilder** ([[anchor-balatro]]) | The score-multiplier crescendo; each joker its own beat |
|
|
64
|
+
| **Precision platformer** ([[genre-precision-platformer]]) | Dust on land, shake on death, snappy landing — feel that rewards clean movement |
|
|
65
|
+
| **Rhythm** ([[genre-rhythm]]) | Feedback *on the beat* — sim time drives both the hit and its flourish (FUN.md §18) |
|
|
66
|
+
|
|
67
|
+
## Overdone when…
|
|
68
|
+
|
|
69
|
+
- **Juice smothers the read.** Constant shake and particle spam bury the avatar and
|
|
70
|
+
the threat — feel that fights [[pattern-readability]]. Reserve the big
|
|
71
|
+
choreography for the big events (the 2-senses contract, not the 5-senses assault).
|
|
72
|
+
- **Nausea shake.** Trauma that doesn't decay fast reads as motion sickness; the
|
|
73
|
+
feedback gate caps it (JUICE.md Part 2).
|
|
74
|
+
- **Hitch hit-stop.** Freezes > ~12 frames read as a bug, not weight.
|
|
75
|
+
- **Juice bound to state, not events.** If the view reads back state it influences,
|
|
76
|
+
determinism breaks and the replay diverges — law 6 violated. Wire to events.
|
|
77
|
+
- **Seizure-bright / frantic.** The judge flags it as a *high*-severity juice-restraint
|
|
78
|
+
failure (JUDGE.md rubric 4).
|
|
79
|
+
|
|
80
|
+
## Verify / feel-gate link
|
|
81
|
+
|
|
82
|
+
Feel is made **checkable** — this is the whole point of Channel 4:
|
|
83
|
+
|
|
84
|
+
- **Declare a `FeedbackContract`, then gate it** (JUICE.md Part 3):
|
|
85
|
+
`feedbackIssues(FEEDBACK, [...]).length === 0` asserts every listed event answers
|
|
86
|
+
on ≥ 2 senses with bounded juice. A silent one-channel event is now a failing test.
|
|
87
|
+
- **Camera smoothness.** `cameraIssues(camSamples).length === 0` — no snaps or jerk
|
|
88
|
+
(the pattern's timing rail; JUICE.md Part 4 lists the frame-1 snap gotchas).
|
|
89
|
+
- **Determinism (FUN.md law 6).** Run headless, hash; run with view, hash; assert
|
|
90
|
+
equal. Proves the choreography is cosmetic — the view is deletable.
|
|
91
|
+
- **The vision judge (JUDGE.md rubric 4 & 5).** Juice restraint and motion clarity
|
|
92
|
+
are scored from the actual pixels — feel gates can pass while the *image* still
|
|
93
|
+
reads as noise; the judge closes that mile.
|
|
94
|
+
|
|
95
|
+
## Worked micro-example
|
|
96
|
+
|
|
97
|
+
*"A sword swing that feels like it lands."* The sim resolves the hit instantly and
|
|
98
|
+
returns a script: `{ hit: true, at: pos, hitstop: 5, knockback: dir }`. The view
|
|
99
|
+
performs it — `Shaker.addTrauma(0.12)`, a `PARTICLE_PRESETS.hit()` burst at `pos`, a
|
|
100
|
+
5-frame freeze that *buffers* the next input through it, an `audio.tone` that pitches
|
|
101
|
+
up on a combo, and a `FloatingText` damage pop. That's the **2-senses contract** met
|
|
102
|
+
several times over (sfx + particles + flash + shake), all cosmetic, all driven off
|
|
103
|
+
the *event* not read-back state. Delete the whole view and the sim hash is identical
|
|
104
|
+
(FUN.md law 6). Prove it: run headless, hash; run with view, hash; assert equal — and
|
|
105
|
+
`feedbackIssues(FEEDBACK, ['hit']).length === 0` guards the ≥2-senses rule.
|
|
106
|
+
|
|
107
|
+
## Composes with
|
|
108
|
+
|
|
109
|
+
- [[pattern-readability]] — juice must *serve* the read, never bury it; the two are
|
|
110
|
+
in constant tension and readability wins ties.
|
|
111
|
+
- [[pattern-pacing-and-tension]] — reserve the loudest choreography for the peaks so
|
|
112
|
+
it stays meaningful.
|
|
113
|
+
- [[pattern-anti-frustration]] — a death that *feels* clean (readable cause, quick
|
|
114
|
+
reset) is half feel, half forgiveness.
|
|
115
|
+
- [[system-combat-model]] — hit-stop and i-frames are where the *shape of a hit* and
|
|
116
|
+
its choreography meet.
|
|
117
|
+
|
|
118
|
+
## See also
|
|
119
|
+
|
|
120
|
+
- [`docs/JUICE.md`](../../docs/JUICE.md) — the full cookbook; **the** reference for
|
|
121
|
+
this pattern. Copy from [`examples/updrift`](../../examples/updrift).
|
|
122
|
+
- [`docs/FUN.md`](../../docs/FUN.md) law 6 — the cosmetic-view rule that makes juice
|
|
123
|
+
free.
|
|
124
|
+
- [`sandboxes/juice-lab`](../../sandboxes/juice-lab) — the juice primitives in isolation.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: pattern-mastery-and-flow
|
|
3
|
+
title: Mastery & Flow
|
|
4
|
+
kind: pattern
|
|
5
|
+
tags: [flow, mastery, challenge, skill, difficulty, engagement, learning-curve, skill-delta]
|
|
6
|
+
summary: Keep challenge riding just above current skill — the flow channel — and prove it with the skill-delta gap.
|
|
7
|
+
use-when: Setting difficulty, ramp, or the depth ceiling; deciding whether skill actually changes outcomes.
|
|
8
|
+
composes-with: [pattern-feedback-loops, pattern-pacing-and-tension, system-mastery-curve, system-difficulty-and-dda]
|
|
9
|
+
verify-with: docs/FUN.md#part-1-—-universal-laws
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Mastery & Flow
|
|
13
|
+
|
|
14
|
+
**What it is.** **Flow** is the state where challenge tracks skill so closely that
|
|
15
|
+
attention locks: too easy and the player is bored, too hard and they're anxious.
|
|
16
|
+
The design job is to keep play inside that narrow **flow channel** as the player's
|
|
17
|
+
skill climbs — the difficulty rises to meet a rising player. **Mastery** is the
|
|
18
|
+
channel's ceiling: how far skill can keep buying results.
|
|
19
|
+
|
|
20
|
+
**Player fantasy.** *"I'm getting better and the game noticed."* The near-miss that
|
|
21
|
+
pulls you back in; the run where you finally read the pattern; the moment a wall
|
|
22
|
+
becomes a warm-up. Time disappearing.
|
|
23
|
+
|
|
24
|
+
## Why it works
|
|
25
|
+
|
|
26
|
+
- **Boredom and anxiety are the two failure modes**, and they sit on either side of
|
|
27
|
+
the same line. Flow is the ridge between them; the ramp is how you walk it upward.
|
|
28
|
+
- **The skill-delta *is* the flow proof.** FUN.md law 2: run the intended strategy
|
|
29
|
+
and a null strategy and assert the gap. That gap is the operational definition of
|
|
30
|
+
"skill matters here" — no gap, no channel, no flow, just noise. This is the fun
|
|
31
|
+
proxy the whole engine leans on.
|
|
32
|
+
- **Learnable depth keeps the channel open.** A high skill *ceiling* ([[system-mastery-curve]])
|
|
33
|
+
means the player can keep climbing without you authoring infinite content —
|
|
34
|
+
Tetris has no level 900 assets, just a faster you.
|
|
35
|
+
- **The channel is per-player, not per-game.** Two players of different skill both
|
|
36
|
+
deserve flow at once. You reach both by *widening* the channel (assist options, a
|
|
37
|
+
high ceiling over a gentle floor), not by picking one difficulty and hoping.
|
|
38
|
+
|
|
39
|
+
## Levers
|
|
40
|
+
|
|
41
|
+
| Lever | Moves the channel | Example |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| **Ramp slope** | How fast challenge rises | Level times/spawn curves that track completion |
|
|
44
|
+
| **Skill ceiling** | How high mastery can climb | Tech, movement tech, combos, optimisation ([[system-mastery-curve]]) |
|
|
45
|
+
| **Failure cost** | Anxiety dial | Instant retry (low) vs run-loss (high) — see [[system-grace]] |
|
|
46
|
+
| **Onboarding** | Where the channel *starts* | Teach-by-doing so the floor isn't a wall ([[system-onboarding]]) |
|
|
47
|
+
| **DDA** | Auto-centres the channel | Nudge difficulty to the measured player ([[system-difficulty-and-dda]]) |
|
|
48
|
+
| **Assist / options** | Widens the channel per-player | Slow-mo, invincibility (Celeste); flow for more people |
|
|
49
|
+
|
|
50
|
+
## Applied across genres
|
|
51
|
+
|
|
52
|
+
| Genre | Where flow lives | The mastery ceiling |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| **Precision platformer** ([[genre-precision-platformer]]) | Each screen just past the last verb | Movement tech, optimal routing, deathless runs |
|
|
55
|
+
| **Endless arcade** ([[anchor-tetris]], [[anchor-nuclear-throne]]) | The self-raising speed curve | Pure execution; the wall *is* the player |
|
|
56
|
+
| **Bullet hell** ([[genre-bullet-hell]]) | Fire-lane uptime under rising density | Reading patterns, holding fire under pressure (FUN.md §7) |
|
|
57
|
+
| **Tactics** ([[genre-tactics]]) | The optimal line hidden in a legible board | Perfect-clears; seeing three moves deep |
|
|
58
|
+
| **Rhythm** ([[genre-rhythm]]) | Window accuracy vs chart density | Frame-tight timing, full-combo chains (FUN.md §18) |
|
|
59
|
+
| **Racing** ([[genre-racing]]) | The line at the edge of grip | Braking discipline, the speed/line tradeoff (FUN.md §20) |
|
|
60
|
+
| **Roguelite** ([[system-meta-progression]]) | Run knowledge + build reading | System mastery outpacing unlock power |
|
|
61
|
+
|
|
62
|
+
## Overdone when…
|
|
63
|
+
|
|
64
|
+
- **The wall with no ramp.** Difficulty jumps a cliff — anxiety, not challenge.
|
|
65
|
+
Break the spike into a slope ([[pattern-pacing-and-tension]]).
|
|
66
|
+
- **The plateau.** Skill stops buying results (a hard cap, a dominant strategy) —
|
|
67
|
+
boredom. A collapsed [[system-build-diversity]] flattens the ceiling.
|
|
68
|
+
- **Difficulty by unfairness.** Faster balls, more HP, coin-flip deaths — that's
|
|
69
|
+
*anxiety without skill expression*, the opposite of flow (FUN.md §7: density ≠
|
|
70
|
+
difficulty; §19: speed ≠ harder).
|
|
71
|
+
- **DDA that erases skill.** Rubber-banding so hard that playing well is pointless
|
|
72
|
+
is a [[pattern-feedback-loops]] gone wrong — the channel should *centre*, not
|
|
73
|
+
*flatten*.
|
|
74
|
+
- **A ceiling the player can't see.** Depth exists but nothing signposts it, so the
|
|
75
|
+
expert doesn't know there's more to climb ([[pattern-readability]]) — the mastery
|
|
76
|
+
is real but invisible, and invisible depth reads as a plateau.
|
|
77
|
+
|
|
78
|
+
## Verify / feel-gate link
|
|
79
|
+
|
|
80
|
+
Flow is not directly measurable, but its precondition — *skill changes outcomes* —
|
|
81
|
+
is the single most important assertion in FUN.md:
|
|
82
|
+
|
|
83
|
+
- **Skill-delta (law 2).** `expect(smartScore).toBeGreaterThan(nullScore * K)` —
|
|
84
|
+
greedy 158 vs random 82, judgement 19/20 vs recklessness 0/20, braking 26.2s vs
|
|
85
|
+
flooring 27.7s. No gap = no flow channel exists to walk.
|
|
86
|
+
- **Ramp legibility.** Per-level bot completion times *expose* the ramp (FUN.md §2)
|
|
87
|
+
— a flat or inverted curve is a difficulty bug you can see in the numbers.
|
|
88
|
+
- **Grace bounds anxiety (law 5).** Coyote/buffer/i-frames/instant-retry keep the
|
|
89
|
+
anxious side of the channel humane; spec them in frames and gate edge-in/edge-out.
|
|
90
|
+
- **Mastery ceiling.** Pairs with [[system-mastery-curve]] — prove an *expert* line
|
|
91
|
+
meaningfully beats a *competent* one, not just skill vs null.
|
|
92
|
+
|
|
93
|
+
## Worked micro-example
|
|
94
|
+
|
|
95
|
+
*"A platformer that stays in flow for a beginner and an expert."* One difficulty
|
|
96
|
+
number can't serve both — a floor for the beginner is a plateau for the expert. Widen
|
|
97
|
+
the channel instead of moving it: (1) the *ramp* teaches each verb one screen before
|
|
98
|
+
it's required ([[system-onboarding]]) so the floor isn't a wall; (2) a high **skill
|
|
99
|
+
ceiling** — optional deathless/speed routes let the expert keep climbing
|
|
100
|
+
([[system-mastery-curve]]); (3) **assist options** (slow-mo, invuln) widen the floor
|
|
101
|
+
for players who'd otherwise fall out of the channel entirely ([[system-accessibility]]).
|
|
102
|
+
Prove the ceiling with a two-tier skill-delta: an *expert* line meaningfully beats a
|
|
103
|
+
*competent* one, not just skill vs null (FUN.md law 2).
|
|
104
|
+
|
|
105
|
+
## Composes with
|
|
106
|
+
|
|
107
|
+
- [[system-mastery-curve]] — this pattern is the *why*; that system is the *how* of
|
|
108
|
+
building a high, learnable ceiling. Read them together.
|
|
109
|
+
- [[system-difficulty-and-dda]] — the mechanism that keeps the channel centred as
|
|
110
|
+
skill rises.
|
|
111
|
+
- [[pattern-pacing-and-tension]] — flow over a session is a curve of peaks and
|
|
112
|
+
breathers, not a constant.
|
|
113
|
+
- [[pattern-feedback-loops]] — the negative loop that stops a snowball is also what
|
|
114
|
+
keeps a match inside the flow channel for both players.
|
|
115
|
+
|
|
116
|
+
## See also
|
|
117
|
+
|
|
118
|
+
- [`docs/FUN.md`](../../docs/FUN.md) law 2 — the skill-delta, the closest thing to
|
|
119
|
+
a fun proof and the operational test for "is there a flow channel here?".
|
|
120
|
+
- [[system-onboarding]] — where the channel starts; a wall on frame one loses the
|
|
121
|
+
player before flow can begin.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: pattern-pacing-and-tension
|
|
3
|
+
title: Pacing & Tension
|
|
4
|
+
kind: pattern
|
|
5
|
+
tags: [pacing, tension, rhythm, peaks, valleys, breather, session, curve, escalation]
|
|
6
|
+
summary: Tension is a curve, not a constant — alternate peaks and breathers so the finale reads as a peak, not another wave.
|
|
7
|
+
use-when: Shaping a session/level/wave/run; deciding difficulty and intensity over time, not just at one moment.
|
|
8
|
+
composes-with: [pattern-feedback-loops, pattern-mastery-and-flow, pattern-risk-reward, system-session-structure]
|
|
9
|
+
verify-with: docs/FUN.md#8-·-tower-defense
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Pacing & Tension
|
|
13
|
+
|
|
14
|
+
**What it is.** Intensity over time is a **curve**, not a level you set once. A game
|
|
15
|
+
that's flat-out from minute one exhausts; one that's flat-calm bores. The craft is
|
|
16
|
+
**peaks and valleys** — escalating pressure punctuated by **breather beats** — so the
|
|
17
|
+
session breathes, tension recovers, and the finale lands as the *peak* because you
|
|
18
|
+
built up to it.
|
|
19
|
+
|
|
20
|
+
**Player fantasy.** *"I can't stop — but I can catch my breath."* The pull of rising
|
|
21
|
+
stakes, the relief of a lull, the dread of the next climb. A shape you feel even
|
|
22
|
+
when you can't name it.
|
|
23
|
+
|
|
24
|
+
## Why it works
|
|
25
|
+
|
|
26
|
+
- **Tension needs contrast to exist.** A peak only reads as a peak against a valley;
|
|
27
|
+
constant maximum is just noise the player tunes out. The breather *makes* the spike.
|
|
28
|
+
- **Breathers refill the flow tank.** Sustained challenge without recovery slides the
|
|
29
|
+
player from flow into anxiety and quitting ([[pattern-mastery-and-flow]]); the lull
|
|
30
|
+
resets attention so the next peak lands.
|
|
31
|
+
- **The curve can emerge from loops.** [[pattern-feedback-loops]] and
|
|
32
|
+
[[pattern-risk-reward]] build peaks *without hand-scripting* — a snowball is a rising
|
|
33
|
+
slope, a push-your-luck run is a self-authored spike. Design the loop, get the curve.
|
|
34
|
+
- **The valley is where the other systems breathe.** Downtime isn't dead time — it's
|
|
35
|
+
where the shop, the draft, the plan, and the story live. A game with no valleys has
|
|
36
|
+
nowhere to put its [[pattern-risk-reward]] decisions; the breather *is* the choice beat.
|
|
37
|
+
|
|
38
|
+
## Levers
|
|
39
|
+
|
|
40
|
+
| Lever | Shapes the curve | Example |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| **Escalation slope** | How fast pressure rises | Wave HP/spawn ramp; enemy density over a level |
|
|
43
|
+
| **Breather placement** | Where the valleys sit | A runner wave; a safe room; a shop between fights |
|
|
44
|
+
| **Peak spacing** | Rhythm of spikes | Mini-boss every N rooms; a crescendo mid-level |
|
|
45
|
+
| **Finale weight** | The last peak is *the* peak | Gate on "finale is the max", not monotonicity |
|
|
46
|
+
| **Session length** | The whole arc's footprint | Run vs level vs campaign ([[system-session-structure]]) |
|
|
47
|
+
| **Downtime texture** | What a valley *does* | Loot, dialogue, planning, catching your breath ([[pattern-risk-reward]]) |
|
|
48
|
+
|
|
49
|
+
## Applied across genres
|
|
50
|
+
|
|
51
|
+
| Genre | The curve | The breather |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| **Tower defense** ([[genre-tower-defense]]) | Wave intensity climbs to a finale peak | Runner waves are the pressure break (FUN.md §8) |
|
|
54
|
+
| **Horde survival** ([[genre-horde-survival]]) | Superlinear spawn ramp | The level-up pick pauses the tide (FUN.md §6) |
|
|
55
|
+
| **Roguelite** ([[system-session-structure]], [[anchor-hades]]) | Room → room → elite → boss | The shop/reward room between fights |
|
|
56
|
+
| **Bullet hell** ([[genre-bullet-hell]]) | Pattern density escalates per phase | Phase transitions (with mercy clears) reset (FUN.md §7) |
|
|
57
|
+
| **Deckbuilder** ([[genre-deckbuilder]]) | Act → elite → boss | Rest sites; the map-choice planning beat |
|
|
58
|
+
| **Survival horror** ([[genre-survival-horror]]) | Dread accrues on a fuel budget | The lit safe pocket at a traversal's midpoint (FUN.md §16) |
|
|
59
|
+
| **Narrative** ([[genre-narrative-decisions]]) | Stakes rise across the reign | A quiet, low-Δ choice between crises |
|
|
60
|
+
|
|
61
|
+
## Overdone when…
|
|
62
|
+
|
|
63
|
+
- **Monotone escalation.** Every wave strictly harder than the last with no dip —
|
|
64
|
+
the player never recovers and the finale reads as "just another wave, but slower to
|
|
65
|
+
die". Gate on *shape* (each wave ≥ ~55% of the previous, finale peaks), not
|
|
66
|
+
monotonicity (FUN.md §8).
|
|
67
|
+
- **All-breather / no spine.** Endless low-stakes downtime — the game never grips.
|
|
68
|
+
Valleys serve peaks; they aren't the point.
|
|
69
|
+
- **Whiplash pacing.** Peaks and valleys with no ramp between — jarring, not
|
|
70
|
+
rhythmic. Ease into and out of spikes.
|
|
71
|
+
- **The false finale.** The biggest fight sits mid-session and the ending fizzles —
|
|
72
|
+
the curve should *build* to its last peak.
|
|
73
|
+
|
|
74
|
+
## Verify / feel-gate link
|
|
75
|
+
|
|
76
|
+
Pacing is one of the few *aesthetic* concerns FUN.md makes into a hard assertion,
|
|
77
|
+
via the wave-curve gate:
|
|
78
|
+
|
|
79
|
+
- **Assert the shape, not monotonicity (FUN.md §8).** Gate on "each wave ≥ 55% of
|
|
80
|
+
the previous, finale peaks" — a *breathing* curve, with deliberate breather beats,
|
|
81
|
+
not a straight climb. Both CLAWSTRIKE and Norman the Necromancer pace waves with
|
|
82
|
+
explicit breathers (FUN.md §8).
|
|
83
|
+
- **Pressure curve checklist (FUN.md Part 3).** "Wave/pressure curve breathes —
|
|
84
|
+
deliberate breather beats; finale is the peak; assert the shape" is a
|
|
85
|
+
before-you-author-content gate.
|
|
86
|
+
- **No unlock deserts (FUN.md §14).** For incremental/economy arcs, the pacing
|
|
87
|
+
failure is a *desert* — a stretch with no new thing; balance-sim the whole arc and
|
|
88
|
+
assert no gap ([[genre-incremental]]).
|
|
89
|
+
- **Session-length fit** ([[system-session-structure]]) — the curve must fit the
|
|
90
|
+
intended session footprint; a 40-minute arc in a 5-minute run has no room to breathe.
|
|
91
|
+
|
|
92
|
+
## Worked micro-example
|
|
93
|
+
|
|
94
|
+
*"A tower-defense run that builds to a finale instead of grinding flat."* The naive
|
|
95
|
+
curve is monotone — every wave a little harder — and the "finale" reads as just a
|
|
96
|
+
slower-to-die version of wave 12. Shape it instead: (1) **escalate** the combat waves
|
|
97
|
+
in a rising slope; (2) drop a **runner wave** every third slot as a pressure break —
|
|
98
|
+
a valley that lets the player retool and breathe; (3) weight the **finale** as the
|
|
99
|
+
true peak, well above the prior maximum. Now the run has a shape you can feel. Prove
|
|
100
|
+
it with the wave-curve gate (FUN.md §8): assert each wave ≥ ~55% of the previous and
|
|
101
|
+
the finale peaks — a *breathing* curve, not a straight climb, and not monotonicity.
|
|
102
|
+
|
|
103
|
+
## Composes with
|
|
104
|
+
|
|
105
|
+
- [[pattern-feedback-loops]] — loops build the peaks and the comebacks *emergently*;
|
|
106
|
+
the curve falls out of the loop's gain.
|
|
107
|
+
- [[pattern-mastery-and-flow]] — pacing is flow *over time*; breathers keep the
|
|
108
|
+
player on the ridge across a whole session.
|
|
109
|
+
- [[pattern-risk-reward]] — push-your-luck is a self-authored tension spike; the
|
|
110
|
+
player draws their own curve.
|
|
111
|
+
- [[system-session-structure]] — the container (run/level/campaign) sets the arc's
|
|
112
|
+
length and where its peaks can sit.
|
|
113
|
+
|
|
114
|
+
## See also
|
|
115
|
+
|
|
116
|
+
- [`docs/FUN.md`](../../docs/FUN.md) §8 (wave curves breathe) & §14 (no deserts) —
|
|
117
|
+
the two places pacing becomes an assertion.
|
|
118
|
+
- [[anchor-hades]] — room-shop-room-boss rhythm as a whole-game pacing spine.
|
|
119
|
+
- [[system-encounter-design]] — a single encounter has its own micro-curve (pressure
|
|
120
|
+
then pocket); pacing is that shape nested up to the session.
|