Close
Simone Seagle

Simone Seagle

Independent Web and Educational Software Developer

Read More

Search

Play

Skeletons as Artisans

Mouse-over or touch/drag to interact with Skeletons as Artisans Or, view fullscreen.

About the Art

If you want wonderful, creepy, poignant Dia de los Muertos images, you really can't beat José Guadalupe Posada's. José Guadalupe Posada was an incredibly prolific Mexican cartoonist and printmaker living in the late 1800s and early 1900s. He often used skeletons as for political commentary, and is thought to have made over 20,000 prints altogether (skeletons and otherwise!). This piece, "Skeletons as Artisans," is from the Metropolitan Museum of Art's Open Access collection and was done between 1890 and 1910.

About the Programming

After making 26 works for the Edward Lear Alphabet project, I felt like I needed a long break from animating artwork, so this is my first in quite some time. Surprisingly, this is my first experiment with programming skeletons (like... the bones of a character), and the artwork couldn't be more appropriate. In fact, I'd been thinking about doing this work for YEARS and just hadn't gotten around to it.

To do this, I used a similar shortcut that I used for Edward Lear, where I define all of the sprites in an array and assign their behaviors in order to keep it all clean. I used some of my favorite tricks here - teetering, creepy watching, and head turning. Adding an additional bone to the skeletons wasn't much work, really. All you need to do is define an attachment point that's a fraction just like an anchor, and then teeter the child bone just like the the parent bone is teetered.


let skeleton = function(sprite) {
    // First we teeter the sprite...
    teeter(sprite);

    // Then we update the child bone
    let x = sprite.x + sprite.boneLength * scale * sprite.attachment.x * Math.cos(sprite.rotation);
    let y = sprite.y + sprite.boneLength * scale * sprite.attachment.y * Math.sin(sprite.rotation);

    sprite.child.x = x;
    sprite.child.y = y;

    // Lazy like a boss... The teeter function sets the location to the sprite's home,but we don't want that because that bone needs to remain attached to its parent
    teeter(sprite.child);

    sprite.child.x = x;
    sprite.child.y = y;
}

My other fun addition was the skeleton in the center. I wanted the two arms and the shoe to move in unison, so their behavior is detached somewhat and is handled by a frequency modulation in the main program. I had to spend some time finessing this, so the math is more magic numbers than actual computations. I needed the laces to BASICALLY stay lined up with the hands, and there might be some way to do the geometry, but... yeah I dunno. It's a job for MAGIC NUMBERS.

let coordinatedBob = function (sprite) {
    let wave = -1 * smod * Math.PI * 0.11;
    sprite.rotation = wave;

    sprite.y = scale * (sprite.home.y - 15 * smod);
    sprite.x = scale * (sprite.home.x + 10 * smod);
}

let coordinatedTeeter = function (sprite) {
    let wave = smod * Math.PI * 0.06;
    sprite.rotation = wave + sprite.offset;
}

let frame = 0;
let smod = 0;
let lambda = 40;
let baselambda = 40;
app.ticker.add(function() {
    frame++;
    // Tween the wavelength for NO JITTERS
    if (distance(trackLoc.x, trackLoc.y, centercenter.x * scale, centercenter.y * scale) < interactionDistance) {
        lambda += (30 - lambda) * 0.03;
    } else lambda += (baselambda - lambda) * 0.05;

    smod = Math.sin(frame/lambda);

    interactiveSprites.forEach(sprite=>sprite.interact(sprite));
});