Your first 30 minutes

From an empty tab to a night full of fireflies that react to the mouse, make sound and turn into a video. Six steps, each a complete sketch you can run: open the IDE, press Test in Dana (or paste the code into a new tab and press Run), then try the small change suggested under it. No C# knowledge needed; it comes along the way.

On this page · 6 entries
What you'll build. One sketch, six steps: a night sky full of fireflies that glow, wander, flee the mouse and multiply when you click — about 60 lines of C#. This reel was made with the IDE's own reel export.

1. A canvas and a circle 3 min

Every sketch is a class that inherits from Sketch. Setup() runs once: give the canvas a size. Draw() runs about 60 times a second: clear the background and draw. MouseX and MouseY are always where the mouse is, so the circle follows it.

C#
public class Fireflies : Sketch
{
    public override void Setup()
    {
        Size(800, 500);
    }

    public override void Draw()
    {
        Background(15, 20, 40);
        Fill(255, 230, 120);
        NoStroke();
        Circle(MouseX, MouseY, 20);
    }
}
Try: Change the background to Background(40, 10, 30), or make the circle bigger when it's further right: Circle(MouseX, MouseY, MouseX / 10).

2. Shapes and color: a night scene 5 min

Drawing is done in order, like painting: what you draw later covers what came before. Fill() and Stroke() set the colors for everything drawn after them, and a fourth number is transparency (0 to 255). Moving the scene into its own method keeps Draw() readable. RandomSeed(7) makes Random() return the same numbers every frame, so the grass doesn't flicker.

C#
public class Fireflies : Sketch
{
    public override void Setup()
    {
        Size(800, 500);
    }

    public override void Draw()
    {
        Background(15, 20, 40);
        DrawScene();

        Fill(255, 230, 120);
        NoStroke();
        Circle(MouseX, MouseY, 20);
    }

    void DrawScene()
    {
        // The moon: a big pale circle with a soft halo behind it.
        NoStroke();
        Fill(255, 255, 220, 30);
        Circle(650, 100, 160);
        Fill(250, 245, 220);
        Circle(650, 100, 90);

        // Grass: hundreds of thin lines, a little different each.
        RandomSeed(7);                       // same "random" grass every frame
        StrokeWeight(2);
        for (int x = 0; x < Width; x += 4)
        {
Stroke(30, Random(70, 110), 60);
float h = Random(30, 90);
Line(x, Height, x + Random(-8, 8), Height - h);
        }
    }
}
Try: Add stars: a loop of 80 tiny Circle(Random(Width), Random(300), 2) calls, before the moon.

3. Animation: one firefly 5 min

Noise() is random that changes smoothly: neighbouring inputs give neighbouring outputs, so increasing t a little each frame makes the firefly wander instead of jump. Sin() swings between -1 and 1; scaled to 0..1 it makes the glow breathe. Two circles, a big faint one and a small bright one, look like light.

C#
public class Fireflies : Sketch
{
    float t;

    public override void Setup()
    {
        Size(800, 500);
    }

    public override void Draw()
    {
        Background(15, 20, 40);
        DrawScene();

        // Noise() gives smooth random values: perfect for wandering.
        t += 0.005f;
        float x = Noise(t) * Width;
        float y = Noise(t + 100) * (Height - 120);

        // Sin() pulses between -1 and 1: the glow breathes.
        float glow = (Sin(FrameCount * 0.1f) + 1) / 2;   // 0..1
        NoStroke();
        Fill(255, 230, 120, 40 * glow);
        Circle(x, y, 60);
        Fill(255, 240, 150, 120 + 135 * glow);
        Circle(x, y, 10);
    }

    void DrawScene()
    {
        NoStroke();
        Fill(255, 255, 220, 30);
        Circle(650, 100, 160);
        Fill(250, 245, 220);
        Circle(650, 100, 90);

        RandomSeed(7);
        StrokeWeight(2);
        for (int x = 0; x < Width; x += 4)
        {
Stroke(30, Random(70, 110), 60);
Line(x, Height, x + Random(-8, 8), Height - Random(30, 90));
        }
    }
}
Try: Make it faster by changing 0.005f, or slow the breathing by changing 0.1f.

4. Many fireflies: classes, lists and vectors 7 min

Forty fireflies need forty positions, so each one becomes an object of a small class, kept in a List. A PVector holds an x and a y and supports +, - and *, so moving is f.Pos += step. PVector.FromAngle() turns a noise value into a direction, and every firefly has its own noise Seed and glow Phase, so they don't move or blink together.

C#
public class Fireflies : Sketch
{
    // One class per "thing": each firefly keeps its own position and rhythm.
    class Firefly
    {
        public PVector Pos;
        public float Seed, Phase;
    }

    readonly List<Firefly> flies = new();

    public override void Setup()
    {
        Size(800, 500);
        for (int i = 0; i < 40; i++)
flies.Add(NewFly(Random(Width), Random(Height - 120)));
    }

    Firefly NewFly(float x, float y) => new Firefly
    {
        Pos = new PVector(x, y),
        Seed = Random(1000),
        Phase = Random(TWO_PI),
    };

    public override void Draw()
    {
        Background(15, 20, 40);
        DrawScene();
        float t = FrameCount * 0.01f;
        NoStroke();
        foreach (var f in flies)
        {
// Each one wanders by its own noise, and wraps around the edges.
var step = PVector.FromAngle(Noise(f.Seed, t) * TWO_PI * 2) * 1.2f;
f.Pos += step;
f.Pos.X = (f.Pos.X + Width) % Width;
f.Pos.Y = Constrain(f.Pos.Y, 10, Height - 100);

float glow = (Sin(FrameCount * 0.08f + f.Phase) + 1) / 2;
Fill(255, 230, 120, 40 * glow);
Circle(f.Pos.X, f.Pos.Y, 50);
Fill(255, 240, 150, 100 + 155 * glow);
Circle(f.Pos.X, f.Pos.Y, 8);
        }
    }

    void DrawScene()
    {
        NoStroke();
        Fill(255, 255, 220, 30);
        Circle(650, 100, 160);
        Fill(250, 245, 220);
        Circle(650, 100, 90);

        RandomSeed(7);
        StrokeWeight(2);
        for (int x = 0; x < Width; x += 4)
        {
Stroke(30, Random(70, 110), 60);
Line(x, Height, x + Random(-8, 8), Height - Random(30, 90));
        }
        RandomSeed((int)Millis());                // back to real randomness
    }
}
Try: Give each firefly its own size or color by adding a field to the class.

5. Interaction: mouse and keyboard 5 min

Methods like MousePressed() and KeyPressed() are called once per event: a click adds five fireflies, Space switches their mood. Inside Draw(), the vector from the mouse to each firefly decides how it reacts: SetMag() keeps the direction and sets the strength, which Map() makes stronger the closer the mouse is.

C#
public class Fireflies : Sketch
{
    class Firefly
    {
        public PVector Pos;
        public float Seed, Phase;
    }

    readonly List<Firefly> flies = new();
    bool scared = true;

    public override void Setup()
    {
        Size(800, 500);
        for (int i = 0; i < 40; i++)
flies.Add(NewFly(Random(Width), Random(Height - 120)));
    }

    Firefly NewFly(float x, float y) => new Firefly
    {
        Pos = new PVector(x, y),
        Seed = Random(1000),
        Phase = Random(TWO_PI),
    };

    public override void Draw()
    {
        Background(15, 20, 40);
        DrawScene();
        float t = FrameCount * 0.01f;
        var mouse = new PVector(MouseX, MouseY);
        NoStroke();
        foreach (var f in flies)
        {
var step = PVector.FromAngle(Noise(f.Seed, t) * TWO_PI * 2) * 1.2f;

// Near the mouse: flee from it, or come closer -- Space switches.
var away = f.Pos - mouse;
float d = away.Mag();
if (d < 150)
    step += away.SetMag(Map(d, 0, 150, 3, 0)) * (scared ? 1 : -1);

f.Pos += step;
f.Pos.X = (f.Pos.X + Width) % Width;
f.Pos.Y = Constrain(f.Pos.Y, 10, Height - 100);

float glow = (Sin(FrameCount * 0.08f + f.Phase) + 1) / 2;
Fill(255, 230, 120, 40 * glow);
Circle(f.Pos.X, f.Pos.Y, 50);
Fill(255, 240, 150, 100 + 155 * glow);
Circle(f.Pos.X, f.Pos.Y, 8);
        }

        Fill(255, 150);
        Text($"{flies.Count} fireflies · click: add five · space: {(scared ? "shy" : "curious")}", 12, 20);
    }

    public override void MousePressed()
    {
        for (int i = 0; i < 5; i++)
flies.Add(NewFly(MouseX + Random(-20, 20), MouseY + Random(-20, 20)));
    }

    public override void KeyPressed()
    {
        if (Key == ' ') scared = !scared;
    }

    void DrawScene()
    {
        NoStroke();
        Fill(255, 255, 220, 30);
        Circle(650, 100, 160);
        Fill(250, 245, 220);
        Circle(650, 100, 90);

        RandomSeed(7);
        StrokeWeight(2);
        for (int x = 0; x < Width; x += 4)
        {
Stroke(30, Random(70, 110), 60);
Line(x, Height, x + Random(-8, 8), Height - Random(30, 90));
        }
        RandomSeed((int)Millis());
    }
}
Try: Press a key to clear them all with flies.Clear(), or make the moon follow the mouse.

6. Sound, saving and sharing 5 min

One line of Play() gives each click a note, higher to the right. Save() writes a PNG of the canvas when you press S. The // @reel comments don't change how the sketch runs: they tell Sketch → Create reel... how to turn it into a short video, with the code typing itself scene by scene, then the sketch running with a simulated mouse. Export it as MP4 with sound, a GIF, or a YouTube thumbnail.

C#
// @reel title: Fireflies in 60 lines of C#
// @reel format: vertical
// @reel result: 8 caption="Move the mouse · click to add more"
// @reel scene "A firefly is a position, a seed and a rhythm" effect=type
public class Fireflies : Sketch
{
    class Firefly
    {
        public PVector Pos;
        public float Seed, Phase;
    }

    readonly List<Firefly> flies = new();
    bool scared = true;

    public override void Setup()
    {
        Size(800, 500);
        for (int i = 0; i < 40; i++)
flies.Add(NewFly(Random(Width), Random(Height - 120)));
    }

    Firefly NewFly(float x, float y) => new Firefly
    {
        Pos = new PVector(x, y),
        Seed = Random(1000),
        Phase = Random(TWO_PI),
    };
// @reel scene "Every frame: wander, avoid the mouse, glow" effect=lines
    public override void Draw()
    {
        Background(15, 20, 40);
        DrawScene();
        float t = FrameCount * 0.01f;
        var mouse = new PVector(MouseX, MouseY);
        NoStroke();
        foreach (var f in flies)
        {
var step = PVector.FromAngle(Noise(f.Seed, t) * TWO_PI * 2) * 1.2f;   // @mark
var away = f.Pos - mouse;
float d = away.Mag();
if (d < 150)
    step += away.SetMag(Map(d, 0, 150, 3, 0)) * (scared ? 1 : -1);   // @mark
f.Pos += step;
f.Pos.X = (f.Pos.X + Width) % Width;
f.Pos.Y = Constrain(f.Pos.Y, 10, Height - 100);

float glow = (Sin(FrameCount * 0.08f + f.Phase) + 1) / 2;
Fill(255, 230, 120, 40 * glow);
Circle(f.Pos.X, f.Pos.Y, 50);
Fill(255, 240, 150, 100 + 155 * glow);
Circle(f.Pos.X, f.Pos.Y, 8);
        }
    }
// @reel hide
    public override void MousePressed()
    {
        // A soft note for every new group, higher the further right you click.
        Play(Map(MouseX, 0, Width, 60, 84), synth: Synth.Pluck, amp: 0.5, release: 0.6);
        for (int i = 0; i < 5; i++)
flies.Add(NewFly(MouseX + Random(-20, 20), MouseY + Random(-20, 20)));
    }

    public override void KeyPressed()
    {
        if (Key == ' ') scared = !scared;
        if (Key == 's') Save("fireflies.png");
    }

    void DrawScene()
    {
        NoStroke();
        Fill(255, 255, 220, 30);
        Circle(650, 100, 160);
        Fill(250, 245, 220);
        Circle(650, 100, 90);

        RandomSeed(7);
        StrokeWeight(2);
        for (int x = 0; x < Width; x += 4)
        {
Stroke(30, Random(70, 110), 60);
Line(x, Height, x + Random(-8, 8), Height - Random(30, 90));
        }
        RandomSeed((int)Millis());
    }
}
// @reel show
Try: Open Sketch → Examples for 50+ more sketches, starting with the numbered "YT" series.

Where next: coming from Processing or p5.js, then every section of this reference ends with a runnable example.