Simple sprite animation code in JavaScript

A small piece of code for sprite animation

A few years ago, I was working on an idea for a fantasy football app where players were represented visually on a football field running, throwing, catching and tackling. For each of these player actions, I needed to animate a spritesheet. I made an assessment of the various scripts available at the time, and none of them fit my basic requirements, so I wrote my own home-brewed one.

A few basic requirements I wanted it to cover were:

  1. Play at any speed
  2. Play for a specific number of frames
  3. Play for a specific amount of time
  4. Stop on any specific frame
  5. Stop on the current frame
  6. Play infinitely

The logic turned out to be very staightforward to write and the final function came in at a very light 31 lines of code.

Spritesheet

The sprites on the sheet can be placed anywhere, though it's easiest to to lay them across consistently-sized boundaries so it's easy to calculate the coordinates. In this example sprite, pulled from the game Braid, each sprite is spaced 200px horizontally and vertically and ten across.

The coordinates correlate to the sprite's CSS background position, so the first cell starts at [0,0] with the second cell at [-200,0] and so forth.

Code

I've since used this for every sprite animation need I've had, most notably with the iPhoneception web app. Feel free to use the code for yourself below. It does require jQuery to reference the DOM, but there's no reason this couldn't be easily converted to Vanilla JavaScript.

JAVASCRIPT

// Function
function animateSprite(obj, coordinates, speed, duration, frames, endCoordinates) {
    var curPosition = 0;
    var curStep = 0;
    var incrementCheck = obj.animIncrement >= 0 ? obj.animIncrement + 1 : 0;
    
    obj.animIncrement = incrementCheck;
    var animateSpriteInterval = setInterval(function() {
        if (obj.animIncrement !== incrementCheck) {
            clearInterval(animateSpriteInterval);
            clearTimeout(animateSpriteDuration);
            obj.css({'background-position': endCoordinates[0] + ' ' + endCoordinates[1]});
        }
        obj.css({'background-position': coordinates[curPosition][0] + ' ' + coordinates[curPosition][1]});
        if (frames > 0) {
            if (curStep < frames) {
                curPosition = curPosition < coordinates.length - 1 ? curPosition + 1 : 0;
                curStep = curStep + 1;
            } else {
                clearInterval(animateSpriteInterval);
                obj.css({'background-position': endCoordinates[0] + ' ' + endCoordinates[1]});
            }
        } else {
            curPosition = curPosition < coordinates.length - 1 ? curPosition + 1 : 0;
        }
    }, speed);
    
    if (duration > 0) {
        var animateSpriteDuration = setTimeout (function() {
            clearInterval(animateSpriteInterval);
            obj.css({'background-position': endCoordinates[0] + ' ' + endCoordinates[1]});
        }, duration);
    }
}

// Variables
var sprite = $('#sprite');
var spriteCoordinates = [ [0,0],[-200,0],[-400,0],[-600,0],[-800,0],[-1000,0],[-1200,0],[-1400,0],[-1600,0],[-1800,0],[0,-200],[-200,-200],[-400,-200],[-600,-200],[-800,-200],[-1000,-200],[-1200,-200],[-1400,-200],[-1600,-200],[-1800,-200],[0,-400],[-200,-400],[-400,-400],[-600,-400],[-800,-400],[-1000,-400],[-1200,-400] ];
var endSpriteCoordinates = [0,0];

// Play 100 frames at speed 30
animateSprite(sprite, spriteCoordinates, 30, 0, 100, endSpriteCoordinates);

// Play for 2 seconds at speed 25
animateSprite(thisSprite, spriteCoordinates, 25, 2000, 0, endSpriteCoordinates);

// Play infinitely at speed 100
animateSprite(thisSprite, spriteCoordinates, 100, 0, 0);

// Stop animation
sprite.animIncrement = sprite.animIncrement + 1;

CSS

#sprite {
    width: 200px;
    height: 200px;
    background-image: url('sprite.png');
    background-position: 0 0;
    background-repeat: no-repeat;
}
HTML

<div id="sprite"></div>


Read more