Viking sprite
A 16-frame character sheet (idle, walk, attack, death — one row each)
packed into a 4×4 grid, loaded from /img/viking.png and drawn with
sprite(...).
image(src) is the source value — a path to an image, or an inline
data:image/png;base64,… URI for small sheets — and sprite(image(src), width:, height:, cols:, rows:, frame:) is the displayable textured quad.
cols/rows describe the atlas grid; frame selects a cell (0 =
top-left, row-major) and is floored, so an animated frame: steps crisply
rather than cross-fading.
Here frame: steps across all 16 cells, so the viking runs through every
action — idle, walk, attack, death. The keyframes hold the first cell to
introduce him and the last (the fall) before fading out via an animated
opacity:. Because this sheet has a solid white cell background and its
frames aren’t grid-aligned, key: #ffffff cuts out the background and
anchor: center re-centres each frame’s content so the figure stays put
instead of wandering.
runner "0.0.1";
use std.shapes.*;
use std.anim.*;
scene viking_sprite(duration: Duration = 4.5s) -> Frame {
let bg = rect(width: 1920px, height: 1080px, fill: #ffffff);
// Hold the first cell to introduce the viking, step through all 16 cells
// (4×4: idle, walk, attack, death), then hold the last cell before the fade.
let cycle = animate {
0s => 0,
0.7s => 0,
2.3s => 15,
2.9s => 15,
};
// Fade in to introduce, hold, fade out by 3.5s, then stay blank white for
// ~1s before the loop restarts.
let fade = animate {
0s => 0,
0.3s => 1,
2.9s => 1,
3.5s => 0,
4.5s => 0,
};
// The sheet's background is already transparent, so no key: is needed;
// anchor: re-centres each frame's content; opacity: drives the fade.
let viking = sprite(
image("/img/viking-transparent.png"),
width: 900px, height: 900px,
cols: 4, rows: 4, frame: cycle, anchor: center, opacity: fade,
);
compose [bg, viking]
}