CineCode
Tutorials

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:

src/main.rs
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:

scenes/intro.ccs
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 highlight
  • dim β€” how much to fade the others (0 = untouched, 1 = invisible)
  • start, dur β€” when the spotlight ramps in, as raw frames or helpers such as sec(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 end

This 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:

The src/main.rs above, typed out, with the spotlight walking from the division (line 2) to the println (line 3).
Files that made this video

A small tutorial project: `src/main.rs` is typed, then the script spotlights line 2 and line 3.

scenes/intro.ccs
Adds the line spotlight, underline, and camera timing.
Open full file
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:

src/edit_source.rs (in the example project)
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:

A live refactor of src/edit_source.rs: spotlight the risky line, then insert a guard so normalize() is safe.
Files that made this video

A live refactor scene: the script reads a risky function and animates the inserted guard clause.

codescene.toml
Project manifest: output size, theme, scene order, transitions, and shader names.
Open full file
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 = 18

Expand 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.mp4

Here's the kind of result you're building toward β€” insert animations and a guided spotlight, straight from the example project:

Insert animations reveal new lines of code in place.
Files that made this video

A scene script that creates insert, shift, and spotlight animations.

codescene.toml
Project manifest: output size, theme, scene order, transitions, and shader names.
Open full file
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 = 18

You did it

Your code now performs. Next, you'll add a living diagram beside it.

On this page