Animating code
Direct the viewer's eye by spotlighting, dimming, and editing code on screen.
A documentary isn't just text on a screen β it guides attention. In this lesson you'll make a block of code perform: lines light up, others dim, and the code even edits itself.
We'll keep using the my-video project from the
previous lesson.
Step 0 β Give yourself some code to walk through
The starter src/main.rs is only three lines β not much to spotlight. Replace it
with a small function so there are real lines to direct attention to:
fn divide(a: i32, b: i32) -> i32 {
let result = a / b;
println!("{a} / {b} = {result}");
return result;
}Everything below animates this file. Keep it open β when the script says
βline 2,β it means line 2 here (let result = a / b;).
Step 1 β Spotlight a line
A spotlight raises one line to full brightness and dims the rest. Add this after
your typewriter call:
let code = s.code(read("src/main.rs"), "rust", 96, 150);
code.font_size(38).fade_in(0, 16).typewriter(6, 70);
// After typing finishes (~frame 90), spotlight line 2 β the division
code.spotlight(2, 0.6, 90, 18);spotlight(line, dim, start, dur):
lineβ the 1-based line to highlightdimβ how much to fade the others (0 = untouched, 1 = invisible)start,durβ when the spotlight ramps in, as raw frames or helpers such assec(3)/ms(600)
Lines are 1-based, matching your editor. Line 1 is the first line of the
block you passed to s.code().
Step 2 β Move the spotlight
Call spotlight again to shift focus to another line. Each call animates from
the previous state:
code.spotlight(2, 0.6, 92, 18); // focus line 2 β the division
s.underline(code, 2, 98, 12); // underline it as you explain
code.spotlight(3, 0.6, 150, 24); // then slide focus to line 3 β the println
code.unfocus(200, 16); // release everyone at the endThis is the core grammar of a CineCode walkthrough: type the code, then walk
the spotlight down it as your narration explains each part. Here is that exact
script, rendered against the divide function above:
Files that made this video
A small tutorial project: `src/main.rs` is typed, then the script spotlights line 2 and line 3.
let s = scene("Intro", 220);
let code = s.code(read("src/main.rs"), "rust", 96, 150);
code.font_size(38).fade_in(0, 16).typewriter(6, 70);
code.spotlight(2, 0.6, 92, 18);
s.underline(code, 2, 98, 12);
code.spotlight(3, 0.6, 150, 24);
code.unfocus(200, 16);Step 3 β Underline and point
Spotlights aren't the only way to draw the eye. You can underline a line or drop an arrow that points at it:
// Animate an underline beneath line 3
s.underline(code, 3, 100, 20);
// An arrow that points at line 4 from a screen position
s.point_at(code, 4, 700, 320, 120, 20);See Highlight & focus code for the full
set, including surround (a box around a range of lines).
Step 4 β Edit the code live
Code can change on screen β perfect for showing a refactor. The example project
ships this real file, where max could be 0 and crash the divide:
fn normalize(values: &mut [f32]) {
let max = peak(values);
for v in values.iter_mut() {
*v = *v / max;
}
}The script reads that file, spotlights the risky let max line, then inserts
a guard clause so the function is safe β all on screen. The source file itself
is never touched; the animation does the editing:
Files that made this video
A live refactor scene: the script reads a risky function and animates the inserted guard clause.
scenes = ["scenes/intro.ccs", "scenes/terrain.ccs", "scenes/pathfind.ccs", "scenes/particles.ccs", "scenes/graph.ccs", "scenes/life.ccs", "scenes/boids.ccs", "scenes/tweens.ccs", "scenes/inserts.ccs", "scenes/edit.ccs", "scenes/edit_source.ccs", "scenes/editor_theme.ccs", "scenes/font_set.ccs", "scenes/remove_styles.ccs", "scenes/morph.ccs", "scenes/shapes.ccs", "scenes/effects.ccs"]
theme = "dark_documentary"
[episode]
title = "How Rivers Form"
[output]
fps = 30
width = 1280
height = 720
[shaders]
aurora = "shaders/aurora.wgsl"
glitch = "shaders/glitch.wgsl"
scanlines = "shaders/scanlines.wgsl"
[transition]
kind = "crossfade"
frames = 18Expand Files that made this video here and compare src/edit_source.rs with
scenes/edit_source.ccs. The Rust file is the before-state; the scene script is
where the new guard clause is animated into place.
For a single line, the simplest pattern is backspace_to and retype (covered
in detail in Edit code live):
let code = s.code(read("src/main.rs"), "rust", 96, 160);
code.fade_in(0, 12).typewriter(6, 60);
// Remove back to a kept prefix, then type the corrected version
code.backspace_to(" return a / b", 90, 20);
code.retype(" if b == 0 { return 0 }\n return a / b", 110, 40);Step 5 β Render
./target/release/cinecode render my-video -o my-video.mp4Here's the kind of result you're building toward β insert animations and a guided spotlight, straight from the example project:
Files that made this video
A scene script that creates insert, shift, and spotlight animations.
scenes = ["scenes/intro.ccs", "scenes/terrain.ccs", "scenes/pathfind.ccs", "scenes/particles.ccs", "scenes/graph.ccs", "scenes/life.ccs", "scenes/boids.ccs", "scenes/tweens.ccs", "scenes/inserts.ccs", "scenes/edit.ccs", "scenes/edit_source.ccs", "scenes/editor_theme.ccs", "scenes/font_set.ccs", "scenes/remove_styles.ccs", "scenes/morph.ccs", "scenes/shapes.ccs", "scenes/effects.ccs"]
theme = "dark_documentary"
[episode]
title = "How Rivers Form"
[output]
fps = 30
width = 1280
height = 720
[shaders]
aurora = "shaders/aurora.wgsl"
glitch = "shaders/glitch.wgsl"
scanlines = "shaders/scanlines.wgsl"
[transition]
kind = "crossfade"
frames = 18You did it
Your code now performs. Next, you'll add a living diagram beside it.