EngineGodot 4.2 or newer
LanguageGDScript
Attach toCamera2D
Time to run~2 minutes
LevelBeginner
OutputOne file (~45 lines)
DependenciesNone. FastNoiseLite is built in.

The prompt

Open a fresh chat at claude.ai/new, paste, and send.

$ Build me a Godot 4.2+ Camera2D screen shake as a single GDScript, using the trauma model.

# shape
- One script, file shake_camera.gd, attached to a Camera2D.
- No plugins.

# trauma
- A trauma float, 0 to 1, that decays every frame by a @export decay rate (default 1.2 per second).
- add_trauma(amount: float) adds and clamps to 1.

# shake
- Each _process frame, compute shake = trauma * trauma (squared so small trauma is subtle).
- Offset the camera by shake * max_offset, where max_offset is an @export Vector2 (default 24, 16).
- Sample two FastNoiseLite channels (or one noise at two seeds) over time * a @export frequency for the x and y offset, so the motion is smooth noise, not per-frame random.
- Optionally add a small rotation: shake * @export max_roll (default 0.05 rad).
- When trauma is 0, offset and rotation return to zero exactly.

# constraints
- Godot 4 API (Camera2D.offset, FastNoiseLite).
- No magic numbers. Everything tunable is @export.

# return format
- One file. No prose before or after the code.
- Brief comments only on the trauma-squared line and the noise sampling.
Open in Claude ▸ Run · 2 min

What this gets you

The difference between a hit that feels like a hit and a number going down. Call add_trauma(0.3) on a light hit and add_trauma(0.8) on a big one, and the screen responds proportionally, then settles. No lingering wobble, no jarring snap.

Because it is on the camera and driven by a single add_trauma call, anything in your game can shake the screen without knowing anything about the camera.

Why it matters

Trauma squared

Linear shake makes every hit feel the same. Squaring trauma means a 0.3 tap barely nudges the screen while a 0.9 slam rattles it, which matches how impacts actually feel. It is one character of code with an outsized effect.

Noise over random

Reassigning a random offset each frame is the number one reason homemade shake looks cheap, it is visual static. Smooth noise sampled over time gives a believable physical wobble.

Decay built in

Because trauma decays on its own, callers never have to stop the shake. They add an impulse and forget it. That is what makes it drop-in anywhere.

What good output looks like

How to wire it up

  1. Save the output as shake_camera.gd.
  2. Attach it to your Camera2D (the one that follows the player).
  3. From any script with a reference to the camera, call camera.add_trauma(0.5) on an impact.
  4. Tune max_offset, decay and frequency in the inspector until it feels right for your game.

Common gotchas

The shake never stops

Trauma is not decaying. Confirm the decay line runs in _process every frame and that nothing is topping trauma back up.

It looks like buzzing static

You are using random offset instead of noise. Switch to sampling FastNoiseLite over a time accumulator.

The camera drifts off-center

The offset is being added to itself instead of set fresh each frame, or it does not reset to zero at trauma 0. Set offset = computed value each frame, do not accumulate.

Where to go next

  1. Directional shake. Bias the offset along the hit direction for a punchier feel.
  2. Hit stop. Pair a tiny Engine.time_scale dip with the trauma for extra impact.
  3. Rumble. Trigger controller vibration from the same add_trauma call.

Use it however you want

The prompt is CC0, paste it, modify it, ship a game with it. The output Claude gives you is yours. A link back to pixeldex.dev in your project's README helps the next solo dev find this stuff.