Dec 26, 2011

Night #6: Image Sequence Object (with variable speed)

I have an example from Learning Processing which demonstrates how to package a “pre-made” animation (i.e. sequence of images) into an object in Processing so that it can be duplicated many times on screen. For tonight’s example, I’m going to make a new version that improves a few key points.

First, in the original example the the image files are loaded in the class itself. This is problematic. Sure, if you make one object then you are loading files from the hard drive once. However, if you make many objects, then you are loading the same images over and over again which is totally unnecessary (and can cause problems like using too much memory, stuttering if objects are made during draw(), taking too long to start up, etc.).

We can fix this by loading an array of images in setup() and passing it to the object.

Animation a;

void setup() {
  // Load the image sequence first!
  PImage[] seq = new PImage[40];
  for (int i = 0; i < seq.length; i++) {
    seq[i] = loadImage("stick/stick"+nf(i+1,2)+".png"); 
  }

  // Now when you make the animation object, you pass it the image array!
  a = new Animation(seq);  
}

The class then receives the array in the constructor and passes it to its own array.

class Animation {
  // The array of images
  PImage[] images;
  
  Animation(PImage[] images_) {
    images = images_;
  }

This way (as you’ll see in the example) if we make an array of objects, each one uses the same array of images (which we loaded only once). Another feature of this improvement is that the Animation object is more generic, and can be created with any arbitrary array of images.

The original example demonstrated how to have the sequences start at different images so that they didn’t all appear to be perfectly in sync. However, the question I usually get is instead: “How can the sequences play back at variable speeds?”

The original example used an integer to keep track of the current “frame” of the animation.

int index = 0;

void next() {
  index = (index + 1) % images.length;
}

Here, you see that we move one spot in the array each frame, and the animation is then shown at the frame rate of our sketch. So in theory, you could change the above to “index = index + 2″ to, say, double the speed. A more flexible way to vary the rate of the animation, however, is to use a float for the index in the array, i.e.

float index = 0;
float speed = random(1,5);

void next() {
  // Move the index forward in the animation sequence
  index += speed;
  // If we are at the end, go back to the beginning
  if (index >= images.length) {
    // We could just say index = 0
    // but this is slightly more accurate
    index -= images.length;
  } 
}

Of course, you can’t actually use this float when you go to look up an image in the array — indices must be integers! So we simply convert it to an int when the time comes to draw the image.

void display() {
  int imageIndex = int(index);
  image(images[imageIndex], x, y);
}

Here is the example.

Download source: AnimationExample.zip