Pixelart GIF animation 👾

Fork this turtle, write your own render function, publish!
Test using the GIF export, make sure `Draw different frames` is checked.

#turtlepixel

Log in to post a comment.

/**
    Challenge! Fork this turtle and write your own pixelart animation!

    @param x         0-1 range
    @param y         0-1 range
    @param frame     0-1 range
    @param grid      total grid size
    return `true` for pixel (or number > 0) / `false` for no pixel` (or number == 0)
**/
function render(x, y, frame, grid) {
    return Math.sqrt((x - 0.5) ** 2 + (y - 0.5) ** 2) < (0.1+pingpong(frame*frame) * 0.75);
}



////////////////////////////////////////////////////////////////
// Pixelart GIF animation. Created by Mark Knol 2021
// https://turtletoy.net/turtle/5c567dc937
////////////////////////////////////////////////////////////////

const grid = 25; // min=10, max=100, step=5
const pixel = 175 / grid;
const drawFrame = 1; // min=0, max=1, step=1 (No, Yes)
const debug = 0; // min=0, max=1, step=1 (No, Yes)
let turtle;
function walk(i, frame) {
    const x = i % grid, y = i / grid | 0;
    if (i === 0) turtle = new Slowpoke();
    if (drawFrame && !x && !y) {
        drawRect(turtle, (-grid * 0.5) * pixel, (-grid * 0.5) * pixel, grid * pixel, grid * pixel);
    }
    let density;
    if ((density = render(x / (grid - 1), y / (grid - 1), frame, grid)) > 0) {
        if (!debug) fillRect(turtle, (x - grid * 0.5) * pixel, (y - grid * 0.5) * pixel, pixel, pixel, density);
        drawRect(turtle, (x - grid * 0.5) * pixel, (y - grid * 0.5) * pixel, pixel, pixel);
    }
    return i < grid * grid - 1;
}

function fillRect(turtle, x, y, w, h, density = 1) {
    const d = clamp(density);
    if (d < 0.1) intensity = pixel;
    else if (d < 0.2) intensity = pixel / 2;
    else if (d < 0.3) intensity = pixel / 4;
    else if (d < 0.4) intensity = pixel / 6;
    else if (d < 0.5) intensity = pixel / 8;
    else if (d < 0.6) intensity = pixel / 10;
    else if (d < 0.7) intensity = pixel / 14;
    else if (d < 0.8) intensity = pixel / 18;
    else if (d < 0.9) intensity = pixel / 22;
    else intensity = 0.1;
    for (let ii = 0; ii < h; ii += intensity) {
        turtle.jump(x, y + ii);
        turtle.goto(x + w, y + ii);
    }
    for (let ii = 0; ii < w; ii += intensity) {
        turtle.jump(x + ii, y);
        turtle.goto(x + ii, y + h);
    }
}

function drawRect(turtle, x, y, w, h) {
    turtle.jump(x,y);
    turtle.goto(x+w,y);
    turtle.goto(x+w,y+h);
    turtle.goto(x,y+h);
    turtle.goto(x,y);
}

function pingpong(t) {
    return (t > 0.5 ? 1 - t : t) * 2;
}

function clamp(v, min = 0.0, max = 1.0) {
    return Math.min(Math.max(v, min), max);
}

function mix(x, y, a) {
    return x * (1 - a) + y * a;
}

////////////////////////////////////////////////////////////////
// Slowpoke utility code. Created by Reinder Nijhoff 2019
// https://turtletoy.net/turtle/cfe9091ad8
////////////////////////////////////////////////////////////////

function Slowpoke(x, y) {
    const linesDrawn = {};
    class Slowpoke extends Turtle {
        goto(x, y) {
            const p = Array.isArray(x) ? [...x] : [x, y];
            if (this.isdown()) {
                const o = [this.x(), this.y()];
                const h1 = o[0].toFixed(8)+'_'+p[0].toFixed(8)+o[1].toFixed(8)+'_'+p[1].toFixed(8);
                const h2 = p[0].toFixed(8)+'_'+o[0].toFixed(8)+p[1].toFixed(8)+'_'+o[1].toFixed(8);
                if (linesDrawn[h1] || linesDrawn[h2]) {
                    super.up();
                    super.goto(p);
                    super.down();
                    return;
                }
                linesDrawn[h1] = linesDrawn[h2] = true;
            } 
            super.goto(p);
        }
    }
    return new Slowpoke(x,y);
}