Game Feel, Calmly
“Game feel” is the difference between pressing a button and hitting something. It is built from tiny confirmations: a flash, a hop, a click, a pause, stacked on the moment of impact. This chapter is the Mar toolbox for juice, and one strong opinion about restraint that the example games follow to the letter.
The doctrine: change the object, not the screen
When something gets hit, the temptation is to shake the camera, flash the screen, and spray thirty particles. Resist all three defaults. The doctrine, learned across a shooter, an FPS, and a card game:
Feedback belongs on the thing itself. The foe that was hit flashes; the tray that caught the star hops; the card that resolved glows. Effects attached to objects read instantly and stack cleanly. Effects applied to the whole screen read as chaos, tax readability exactly when the player needs it most, and, on a small phone canvas, make a meaningful fraction of players motion-sick.
So, concretely: never move the whole canvas. No screen shake, no full-screen jitter. When you want “the world felt that”, say it with color and light (a brief darkening of the background band, a one-tick Canvas.Add glow at the impact), not with motion of everything at once. If a player has prefersReducedMotion set (it is right there on the Device record), tone your remaining flashes down further; it costs one boolean and buys real comfort.
The five reliable ingredients
Each of these is a few lines in step plus a timer field in the Model. Impact frames earn a small state record (hitT, flashT, and friends) counting down to zero.
1. Hit flash. Swap the victim’s palette to white (or its own bright variant) for 2 or 3 ticks:
foeColor : Foe -> Color
foeColor foe =
if foe.hitT > 0 then rgb 255 255 255 else foe.baseColor
2. Hit-stop. For big impacts only: freeze the participants for 2 to 4 ticks (skip their movement while stunT > 0). The world around them continues, which is what sells the weight without any camera trickery.
3. Squash and stretch. Canvas.Scale 112 on the group at landing, Canvas.Scale 92 at the top of a jump, two ticks each. Scale on the object’s group, never the world group.
4. Sound on every verb. Chapter 9’s cue list means each player action can carry a click for nearly free. A jump without a sound is a spreadsheet operation; add CJump and it is a jump.
5. Death pacing. When something important dies (especially the player), do not cut instantly to the message. Let the death effect finish, hold a beat of quiet (30 to 50 ticks), then show the text. The FPS shipped this as a deliberate fix after playtests: the pause is what lets a defeat land. A dyingT countdown phase between Playing and Over is the whole implementation.
Telegraphs: feel’s defensive half
Juice confirms what happened; telegraphs announce what is about to. The standard the example games settled on: about 700 milliseconds of warning (roughly 42 ticks) before an enemy’s attack, expressed on the enemy’s own body: a windup crouch (shift the sprite down 2 pixels), a color shift toward its attack color, a rising two-note cue.
The same doctrine applies: the warning lives on the object. A boss whose eyes go red is readable in a crowd; a screen-edge flash could be anyone. Telegraph durations are gameplay constants (players learn them like music), so name them at the top level next to the palette.
Particles, small and meaningful
A particle list is a fine tool at 2D scale: a List of { x, y, vx, vy, t } stepped like everything else and drawn as 2×2 rects. The restraint rules:
- Spawn a handful (4 to 8) per event, with meaning: sparks fly from the impact point, in the direction of the hit.
- Lifetime under half a second; fade by switching to a dimmer color at half-life rather than alpha-ramping every particle.
- Particles are garnish. If removing an effect makes the game unreadable, it was doing a telegraph’s job; promote it to a real telegraph.
The one-in-three rule
Cap any single event at three simultaneous effects (say, flash + sound + 5 sparks). Beyond that, effects mask each other and the next event’s readability suffers: the second enemy’s telegraph has to compete with the first enemy’s death fireworks. The example games that feel best are not the ones with the most juice; they are the ones where every effect can be read. Silence and stillness are what make the loud moments loud.
Feel is a craft of subtraction as much as addition. Add the five ingredients, keep them on the objects, cap the stack, honor reduced-motion, and your game will feel sharp on a MacBook and considerate on a phone, which is most of what “polish” means at this scale.