Stage 06 — The Juice
You will build: nothing mechanically new — and the game will feel twice as good when you're done. Hitstop, screenshake, flash: the three levers that make impacts land. You'll learn: game-feel engineering · restraint — and design decision 3 (cancel policy) gets finalized now that hits have weight. Warm-up — from memory:
- Every state in both machines (player + slime) — draw the two diagrams side by side.
- What happens, node by node, in the first 0.06 seconds of your sword swing?
Why this exists#
Fast-paced is a perception, and perception is manufactured: a few frames of frozen time on impact (hitstop), a camera that flinches (shake), a victim that blinks white (flash). Each is tiny; together they're the difference between "functional" and "crunchy." The craft here is restraint — juice is seasoning, and every lever below has an "amount" that tips from delicious into nauseating. You'll find each tipping point by crossing it on purpose.
Build it#
A — Flash (the shader shelf pays off)#
A white-out material on the victim for ~0.08s when damaged. The
shaders shelf built exactly this muscle:
a canvas_item shader with a flash_amount uniform mixing the sprite toward white, driven
from the damaged signal. Put it on the Hurtbox owner's sprite via the component — so
every future enemy flashes for free. (Write the five-line shader yourself; you know UV,
COLOR, and mix.)
B — Hitstop#
On a connected hit: freeze both fighters for 40–80ms. Two honest techniques — pick one deliberately:
Engine.time_scale = 0.05for a few real milliseconds (an unscaledawait— engine timers scale too, so what do you wait on? solve that; it's the whole trick), then restore. Global, dramatic, affects everything including the camera.- Per-actor: both state machines get a micro-freeze (their processing suspended briefly). Surgical, more plumbing, nothing else in the world stutters.
Try 40ms, then 200ms — feel the tipping point, then set your number. Sword hits and taking hits deserve different amounts; decide both.
C — Screenshake, done the respectable way#
Trauma-based: a trauma: float on the camera that events add to (small hit +0.2, taking
damage +0.5), decaying every frame; actual offset each frame = random within
trauma² * max_offset. The squaring is the secret — small trauma barely whispers, big
trauma bites, and everything decays smoothly. ~20 lines on your Camera2D. Then the
restraint pass: half your first-draft numbers, play, decide.
D — Death deserves a moment#
The slime's died: a flash-white corpse pause (hitstop's cousin), then a shrink-and-pop
tween, then queue_free. Death that takes 0.3 seconds reads as an event; instant
deletion reads as a bug.
E — Decision 3, finalized#
Now that hits have weight, settle the cancel policy for good: dash-cancel on attack recovery? on active frames? attack-cancel out of dash? Play each combination against three slimes. Write the final ruling and its feel rationale in the architecture doc — this is the sentence that defines your combat.
git add . && git commit -m "stage 06: hitstop, trauma shake, flash, death moment; cancel policy final"
Checkpoint — definition of done#
- Every landed hit: flash + hitstop + proportional shake, and it reads as impact
- Taking damage feels distinctly worse than dealing it (numbers differ on purpose)
- The overdone versions were witnessed (write one line: where was each tipping point?)
- Deaths are moments; nothing vanishes frame-perfect
- Decision 3 finalized in the architecture doc
- Zero warnings; committed. Explain: why square the trauma? — with the alternative's failure described, not just "it's smoother."
Stretch (no instructions)#
Directional shake: impacts kick the camera along the hit direction before the random decay takes over. Subtle, and suddenly hits have a vector.
If you get stuck#
- Hitstop freezes forever → your restore path awaited something that's also frozen; the
section-B riddle again — what clock still ticks at
time_scale0.05? - Shake drifts the camera off-center → you're accumulating offset instead of setting it fresh from trauma each frame; the camera's rest position is sacred.
- Flash sticks on → the reset lives in a timer/tween that died with a state change; who owns the flash lifecycle — the component or the state machine? Choose one owner.