This skill covers camera implementation for ZX games. Triggers on "camera follow", "orbit camera", "third person", "first person", "screen shake", "camera lerp", "dead zone", "camera FOV", "side-scroller camera", "top-down camera". **Load references when:** - Full implementations → `examples/camera-examples.md` - Matrix math, lerp/slerp → `references/camera-math.md` - 2D patterns, parallax → `references/side-scroller-patterns.md` - Coordinate conventions → `zx-game-development/references/coordinate-conventions.md`
/plugin marketplace add nethercore-systems/nethercore-ai-plugins/plugin install zx-dev@nethercore-ai-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/camera-examples.mdreferences/camera-math.mdreferences/side-scroller-patterns.mdImplement cameras using ZX FFI. All camera state in static variables for rollback safety.
Coordinate Convention: Y-up, right-handed, -Z forward. When yaw=0, camera looks toward -Z.
| Function | Purpose |
|---|---|
camera_set(x,y,z, tx,ty,tz) | Position + look-at |
camera_fov(degrees) | Field of view (default 60) |
push_view_matrix(m0..m15) | Custom 4x4 view matrix |
| Type | Best For | Complexity |
|---|---|---|
| Follow | Platformers, racing | Simple |
| Orbit | Action-adventure, RPGs | Medium |
| First-Person | FPS, exploration | Medium |
| Fixed | Puzzle, cinematic | Simple |
static mut CAM_X: f32 = 0.0;
static mut CAM_Y: f32 = 5.0;
static mut CAM_Z: f32 = 10.0;
fn update_follow_camera(tx: f32, ty: f32, tz: f32) {
let dt = delta_time();
let t = (5.0 * dt).min(1.0); // Smoothing
unsafe {
CAM_X += (tx - CAM_X) * t;
CAM_Y += (ty + 5.0 - CAM_Y) * t; // Offset above
CAM_Z += (tz + 10.0 - CAM_Z) * t; // Offset behind
}
}
// In render():
camera_set(CAM_X, CAM_Y, CAM_Z, target_x, target_y, target_z);
static mut CAM_YAW: f32 = 0.0;
static mut CAM_PITCH: f32 = 20.0;
static mut CAM_DIST: f32 = 8.0;
fn update_orbit(player: u32) {
let dt = delta_time();
unsafe {
CAM_YAW += right_stick_x(player) * 120.0 * dt;
CAM_PITCH = (CAM_PITCH - right_stick_y(player) * 120.0 * dt)
.clamp(-30.0, 60.0);
}
}
fn get_orbit_pos(tx: f32, ty: f32, tz: f32) -> (f32, f32, f32) {
unsafe {
let yaw = CAM_YAW.to_radians();
let pitch = CAM_PITCH.to_radians();
(
tx - CAM_DIST * yaw.sin() * pitch.cos(),
ty + CAM_DIST * pitch.sin(),
tz + CAM_DIST * yaw.cos() * pitch.cos(),
)
}
}
static mut LOOK_YAW: f32 = 0.0;
static mut LOOK_PITCH: f32 = 0.0;
fn update_first_person(player: u32) {
let dt = delta_time();
unsafe {
LOOK_YAW += right_stick_x(player) * 90.0 * dt;
LOOK_PITCH = (LOOK_PITCH - right_stick_y(player) * 90.0 * dt)
.clamp(-85.0, 85.0);
}
}
fn get_look_dir() -> (f32, f32, f32) {
unsafe {
let yaw = LOOK_YAW.to_radians();
let pitch = LOOK_PITCH.to_radians();
(-yaw.sin() * pitch.cos(), pitch.sin(), -yaw.cos() * pitch.cos())
}
}
// In render():
let (dx, dy, dz) = get_look_dir();
camera_set(player_x, player_y + 1.6, player_z,
player_x + dx, player_y + 1.6 + dy, player_z + dz);
static mut SHAKE_TRAUMA: f32 = 0.0;
fn add_shake(amount: f32) { unsafe { SHAKE_TRAUMA = (SHAKE_TRAUMA + amount).min(1.0); } }
fn update_shake() { unsafe { SHAKE_TRAUMA = (SHAKE_TRAUMA - delta_time() * 2.0).max(0.0); } }
fn get_shake_offset() -> (f32, f32) {
unsafe {
let shake = SHAKE_TRAUMA * SHAKE_TRAUMA * 10.0;
((random_f32() - 0.5) * shake, (random_f32() - 0.5) * shake)
}
}
Prevents jitter when target is near camera center:
fn update_with_dead_zone(tx: f32, tz: f32) {
let dx = tx - CAM_X;
let dz = tz - (CAM_Z - OFFSET_Z);
let dist = (dx*dx + dz*dz).sqrt();
if dist > 2.0 { // DEAD_ZONE
let t = ((dist - 2.0) / dist) * 0.1;
CAM_X += dx * t;
CAM_Z += dz * t;
}
}
| Experience | Best Perspective |
|---|---|
| Character action/story | Third-Person |
| Immersive world | First-Person |
| Precision platforming | Side-Scroller |
| Vehicle/tactical | Top-Down |
All camera state uses static variables (auto-snapshotted). Use delta_time() for frame-rate independence, FFI random() for shake.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.