start

Getting Started

From an empty folder to an AnimaScript script running in a Rive file.

Install rive

rive is Rive’s command line tool. It turns a folder of source files into a Rive file and shows the result in a window that rebuilds every time you save. It carries the AnimaScript compiler and standard library, so there is nothing else to install.

shell
curl -fsSL https://releases.rive.app/cli/install.sh | sh
rive --version

A first project

A project is a folder with a rive.yaml. AnimaScript compiles to WebAssembly, so the project turns it on with scripting: wasm. Without a scene file, the artboard key sizes the artboard the script draws into:

rive.yaml
name: hello
scripting: wasm
artboard:
  width: 800
  height: 600
  background: "#1D1D1D"

A script is an exported class that extends one of the protocol bases in rive/host. The base decides what the script is: a Layout draws into a layout box, a Node draws in the artboard tree, a Converter transforms a data bound value, and PathEffect, ListenerAction, TransitionCondition, Interpolator and Transition do what their names say. The host calls only the hooks your class overrides, and each one is marked override:

main.as
import { Layout, Context } from "rive/host";
import { Renderer } from "rive/renderer";
import { Paint } from "rive/paint";
import { Path } from "rive/path";
import { Vector } from "rive/vector";
import { Color } from "rive/color";

// A square orbiting the artboard.
export class Hello extends Layout {
    paint: Paint = new Paint();
    path: Path = new Path();
    width: f64 = 0;
    height: f64 = 0;
    elapsed: f64 = 0;

    override init(context: Context): bool {
        this.paint.color = Color.rgb(255, 100, 50);
        context.log("hello from rive");
        return true;
    }

    override resize(width: f64, height: f64, scale: f64): void {
        this.width = width;
        this.height = height;
    }

    override advance(seconds: f64): bool {
        this.elapsed += seconds;
        return true;
    }

    override draw(renderer: Renderer): void {
        const w = this.width;
        const h = this.height;
        const cx = w / 2 + Math.cos(this.elapsed) * w * 0.25;
        const cy = h / 2 + Math.sin(this.elapsed * 1.3) * h * 0.25;
        const r = Math.min(w, h) * 0.1;
        const path = this.path;
        path.reset();
        path.moveTo(Vector.xy(<f32>(cx - r), <f32>(cy - r)));
        path.lineTo(Vector.xy(<f32>(cx + r), <f32>(cy - r)));
        path.lineTo(Vector.xy(<f32>(cx + r), <f32>(cy + r)));
        path.lineTo(Vector.xy(<f32>(cx - r), <f32>(cy + r)));
        path.close();
        renderer.drawPath(path, this.paint);
    }
}

Run it, and leave the window open while you edit:

shell
rive .            # the live window, rebuilt on every save
rive . --verify   # check every script without running anything
rive . --test     # run the project's Tests scripts headless

Every .as file in the folder is picked up, and all of them compile into one module. A file without an exported protocol class is a library: other scripts import from it with a relative path, as in import { clamp } from "./math", and from the Rive API with rive/*. rive docs animascript/protocols lists every hook and how a scene attaches a script, and rive docs animascript/api has the whole API, one page per rive/* module.

one language per project

A project with scripting: wasm compiles its .as files. Luau scripts belong in a project without it.

Trying the language here

Examples on this site with a run button compile in your browser with the same compiler rive uses, and run on your browser’s WebAssembly engine. Edit them freely. The in-page runner gives examples a print function for output; scripts in a project use context.log or console.log instead.

greeting.as
export function greet(name: string): string {
    return "hello, " + name;
}
main.as
import { greet } from "./greeting";

declare function print(s: string): void;

export function main(): i32 {
    print(greet("AnimaScript"));
    return 0;
}

From here, Concepts tours the language, Structs covers the data types that make fast code easy, and Threads shows how to move work off the frame.