/camera-system
Use when implementing cameras — smooth follow, screen shake, camera zones, and transitions for 2D and 3D
$ npx -y skills add jame581/GodotPrompter --skill camera-system --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/camera-system
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when implementing cameras — smooth follow, screen shake, camera zones, and transitions for 2D and 3D
SKILL.md
camera-system.SKILL.mdname: camera-system
description: Use when implementing cameras — smooth follow, screen shake, camera zones, and transitions for 2D and 3D
Camera Systems in Godot 4.3+
All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.
> **Related skills:** **player-controller** for first-person camera setup, **state-machine** for camera state transitions, **godot-optimization** for camera culling and performance, **physics-system** for physics interpolation and camera smoothing, **2d-essentials** for canvas layers, parallax scrolling, and coordinate conversion, **math-essentials** for smoothstep and lerp-based interpolation, **tween-animation** for camera shake and cinematic transitions, **phantom-camera** for a Cinemachine-style camera addon.
---
1. Camera2D Basics
Key Properties
| Property | Type | Description | |---|---|---| | `position_smoothing_enabled` | `bool` | Enables built-in position smoothing (lerp toward target) | | `position_smoothing_speed` | `float` | Speed of built-in smoothing (default `5.0`) | | `drag_horizontal_enabled` | `bool` | Enables a horizontal drag zone; camera only moves when target exits zone | | `drag_vertical_enabled` | `bool` | Enables a vertical drag zone | | `limit_left` | `int` | Left pixel boundary — camera will not scroll past this | | `limit_right` | `int` | Right pixel boundary | | `limit_top` | `int` | Top pixel boundary | | `limit_bottom` | `int` | Bottom pixel boundary | | `zoom` | `Vector2` | Zoom level; `Vector2(2, 2)` = 2× zoom in, `Vector2(0.5, 0.5)` = zoom out |
Set limits to match your tilemap or level bounds so the camera never shows outside the world. Limits are in world pixels, not tiles.
---
2. Smooth Follow
A manual follow camera gives more control than the built-in smoothing — you can add look-ahead, offset, and custom easing.
GDScript
extends Camera2D
## Target node to follow (assign in Inspector or via code)
@export var target: Node2D
## How quickly the camera catches up to the target (higher = snappier)
@export var follow_speed: float = 8.0
## How far ahead the camera leads in the movement direction
@export var look_ahead_distance: float = 80.0
## How quickly the look-ahead offset responds to direction changes
@export var look_ahead_speed: float = 4.0
var _look_ahead_offset: Vector2 = Vector2.ZERO
var _previous_target_pos: Vector2 = Vector2.ZERO
func _ready() -> void:
# Disable built-in smoothing — we handle it manually
position_smoothing_enabled = false
if target:
_previous_target_pos = target.global_position
global_position = target.global_position
func _process(delta: float) -> void:
if not target:
return
# Compute movement direction from last frame
var move_delta: Vector2 = target.global_position - _previous_target_pos
_previous_target_pos = target.global_position
# Smoothly steer look-ahead offset toward movement direction
var desired_ahead: Vector2 = move_delta.normalized() * look_ahead_distance if move_delta.length() > 0.5 else Vector2.ZERO
_look_ahead_offset = _look_ahead_offset.lerp(desired_ahead, look_ahead_speed * delta)
# Lerp camera position toward target + look-ahead
var desired_pos: Vector2 = target.global_position + _look_ahead_offset
global_position = global_position.lerp(desired_pos, follow_speed * delta)C#
using Godot;
public partial class SmoothFollowCamera : Camera2D
{
[Export] public Node2D Target { get; set; }
[Export] public float FollowSpeed { get; set; } = 8.0f;
[Export] public float LookAheadDistance { get; set; } = 80.0f;
[Export] public float LookAheadSpeed { get; set; } = 4.0f;
private Vector2 _lookAheadOffset = Vector2.Zero;
private Vector2 _previousTargetPos = Vector2.Zero;
public override void _Ready()
{
PositionSmoothingEnabled = false;
if (Target != null)
{
_previousTargetPos = Target.GlobalPosition;
GlobalPosition = Target.GlobalPosition;
}
}
public override void _Process(double delta)
{
if (Target == null)
return;
float dt = (float)delta;
Vector2 moveDelta = Target.GlobalPosition - _previousTargetPos;
_previousTargetPos = Target.GlobalPosition;
Vector2 desiredAhead = moveDelta.Length() > 0.5f
? moveDelta.Normalized() * LookAheadDistance
: Vector2.Zero;
_lookAheadOffset = _lookAheadOffset.Lerp(desiredAhead, LookAheadSpeed * dt);
Vector2 desiredPos = Target.GlobalPosition + _lookAheadOffset;
GlobalPosition = GlobalPosition.Lerp(desiredPos, FollowSpeed * dt);
}
}---
3. Screen Shake
A trauma-based system produces more natural-looking shake than a simple sine wave. High trauma = violent shake; trauma decays over time; offset scales with `trauma^2` so small trauma values feel subtle.
GDScript
extends Camera2D
## Maximum pixel offset during maximum trauma
@export var max_offset: Vector2 = Vector2(20.0, 15.0)
## Maximum rotation offset in degrees during maximum trauma
@export var max_roll: float = 3.0
## Rate at which trauma decays per second (0–1 range)
@export var decay_rate: float = 1.5
var _trauma: float = 0.0 # 0.0 = no shake, 1.0 = maximum shake
# Optional: use noise for smooth, organic shake
var _noise: FastNoiseLite
var _noise_time: float = 0.0
@export var use_noise: bool = true
@export var noise_speed: float = 60.0
func _ready() -> void:
_noise = FastNoiseLite.new()
_noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
_noise.seed = randi()
## Call this from any node to trigger a shake (amount in 0–1 range; can stack)
func add_trauma(amount: float) -> void:
_trauma = minf(_trauma + amount, 1.0)
func _process(delta: float) -> void:
if _trauma <= 0.0:
offset = Vector2.ZERO
rotation = 0.0
return
# Decay trauma over time
_trauma =Read more
name: camera-system description: Use when implementing cameras — smooth follow, screen shake, camera zones, and transitions for 2D and 3D
Camera Systems in Godot 4.3+
All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.
> **Related skills:** **player-controller** for first-person camera setup, **state-machine** for camera state transitions, **godot-optimization** for camera culling and performance, **physics-system** for physics interpolation and camera smoothing, **2d-essentials** for canvas layers, parallax scrolling, and coordinate conversion, **math-essentials** for smoothstep and lerp-based interpolation, **tween-animation** for camera shake and cinematic transitions, **phantom-camera** for a Cinemachine-style camera addon.
---
1. Camera2D Basics
Key Properties
| Property | Type | Description | |---|---|---| | `position_smoothing_enabled` | `bool` | Enables built-in position smoothing (lerp toward target) | | `position_smoothing_speed` | `float` | Speed of built-in smoothing (default `5.0`) | | `drag_horizontal_enabled` | `bool` | Enables a horizontal drag zone; camera only moves when target exits zone | | `drag_vertical_enabled` | `bool` | Enables a vertical drag zone | | `limit_left` | `int` | Left pixel boundary — camera will not scroll past this | | `limit_right` | `int` | Right pixel boundary | | `limit_top` | `int` | Top pixel boundary | | `limit_bottom` | `int` | Bottom pixel boundary | | `zoom` | `Vector2` | Zoom level; `Vector2(2, 2)` = 2× zoom in, `Vector2(0.5, 0.5)` = zoom out |
Set limits to match your tilemap or level bounds so the camera never shows outside the world. Limits are in world pixels, not tiles.
---
2. Smooth Follow
A manual follow camera gives more control than the built-in smoothing — you can add look-ahead, offset, and custom easing.
GDScript
extends Camera2D
## Target node to follow (assign in Inspector or via code)
@export var target: Node2D
## How quickly the camera catches up to the target (higher = snappier)
@export var follow_speed: float = 8.0
## How far ahead the camera leads in the movement direction
@export var look_ahead_distance: float = 80.0
## How quickly the look-ahead offset responds to direction changes
@export var look_ahead_speed: float = 4.0
var _look_ahead_offset: Vector2 = Vector2.ZERO
var _previous_target_pos: Vector2 = Vector2.ZERO
func _ready() -> void:
# Disable built-in smoothing — we handle it manually
position_smoothing_enabled = false
if target:
_previous_target_pos = target.global_position
global_position = target.global_position
func _process(delta: float) -> void:
if not target:
return
# Compute movement direction from last frame
var move_delta: Vector2 = target.global_position - _previous_target_pos
_previous_target_pos = target.global_position
# Smoothly steer look-ahead offset toward movement direction
var desired_ahead: Vector2 = move_delta.normalized() * look_ahead_distance if move_delta.length() > 0.5 else Vector2.ZERO
_look_ahead_offset = _look_ahead_offset.lerp(desired_ahead, look_ahead_speed * delta)
# Lerp camera position toward target + look-ahead
var desired_pos: Vector2 = target.global_position + _look_ahead_offset
global_position = global_position.lerp(desired_pos, follow_speed * delta)C#
using Godot;
public partial class SmoothFollowCamera : Camera2D
{
[Export] public Node2D Target { get; set; }
[Export] public float FollowSpeed { get; set; } = 8.0f;
[Export] public float LookAheadDistance { get; set; } = 80.0f;
[Export] public float LookAheadSpeed { get; set; } = 4.0f;
private Vector2 _lookAheadOffset = Vector2.Zero;
private Vector2 _previousTargetPos = Vector2.Zero;
public override void _Ready()
{
PositionSmoothingEnabled = false;
if (Target != null)
{
_previousTargetPos = Target.GlobalPosition;
GlobalPosition = Target.GlobalPosition;
}
}
public override void _Process(double delta)
{
if (Target == null)
return;
float dt = (float)delta;
Vector2 moveDelta = Target.GlobalPosition - _previousTargetPos;
_previousTargetPos = Target.GlobalPosition;
Vector2 desiredAhead = moveDelta.Length() > 0.5f
? moveDelta.Normalized() * LookAheadDistance
: Vector2.Zero;
_lookAheadOffset = _lookAheadOffset.Lerp(desiredAhead, LookAheadSpeed * dt);
Vector2 desiredPos = Target.GlobalPosition + _lookAheadOffset;
GlobalPosition = GlobalPosition.Lerp(desiredPos, FollowSpeed * dt);
}
}---
3. Screen Shake
A trauma-based system produces more natural-looking shake than a simple sine wave. High trauma = violent shake; trauma decays over time; offset scales with `trauma^2` so small trauma values feel subtle.
GDScript
extends Camera2D
## Maximum pixel offset during maximum trauma
@export var max_offset: Vector2 = Vector2(20.0, 15.0)
## Maximum rotation offset in degrees during maximum trauma
@export var max_roll: float = 3.0
## Rate at which trauma decays per second (0–1 range)
@export var decay_rate: float = 1.5
var _trauma: float = 0.0 # 0.0 = no shake, 1.0 = maximum shake
# Optional: use noise for smooth, organic shake
var _noise: FastNoiseLite
var _noise_time: float = 0.0
@export var use_noise: bool = true
@export var noise_speed: float = 60.0
func _ready() -> void:
_noise = FastNoiseLite.new()
_noise.noise_type = FastNoiseLite.TYPE_SIMPLEX
_noise.seed = randi()
## Call this from any node to trigger a shake (amount in 0–1 range; can stack)
func add_trauma(amount: float) -> void:
_trauma = minf(_trauma + amount, 1.0)
func _process(delta: float) -> void:
if _trauma <= 0.0:
offset = Vector2.ZERO
rotation = 0.0
return
# Decay trauma over time
_trauma =Agentic skills framework for Godot 4.x game development. Gives AI coding agents domain-specific expertise for GDScript and C# projects.
Other skills on godot-prompter.
- /authoring-godot-prompter-skills
Use when writing or editing a SKILL.md or an agent definition in this repo — required frontmatter, section ordering, and the GDScript-then-C# example convention.
Open skill - /releasing-godot-prompter
Use when cutting a GodotPrompter release or bumping its version — the version-bump sequence, tag-triggered workflow, and the marketplace manifests that must follow.
Open skill - /2d-essentials
Use when working with 2D-specific systems — TileMaps, parallax scrolling, 2D lights and shadows, canvas layers, particles 2D, custom drawing, and 2D meshes in Godot 4.3+
Open skill - /3d-essentials
Use when working with 3D-specific systems — materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion culling, and decals in Godot 4.3+
Open skill - /ability-system
Use when building character abilities — Resource-based abilities with cost/cooldown/cast, buffs/debuffs, stat modifiers, gameplay tags, and HUD binding
Open skill - /addon-development
Use when creating Godot editor plugins — EditorPlugin, @tool scripts, custom inspectors, and dock panels
Open skill

