Timers and Animation

How do GUIs toolkits implement events? What's the underlying mechanism for responding to an event? Do they use existing code?

There are many, many levels to this.

At a very basic level, a voltage spike is sent to some location on the CPU.

Ping!

The CPU responds to this by immediately forcing execution of code at a specific location in memory.

Jump to location 0x35aceef

This code is installed by the operating system during the startup procedure, and the exact location depends on the model of the CPU.

Key was pressed!

The operating system's code stub (known as an interrupt handler) will read information from the hardware to figure out what key was pressed.

It will then look at the list of running applications and decide which (if any) to send the keycode to.

Send information to Processing and the keylogger virus

A similar process occurs on the application end: it registers a function to be run whenever the OS notifies it of input.

Windows told me a key was pressed.

Look for a keyPressed() handler and run it.

How could I write code for both "key pressed" and "key held"?

Processing runs under what Linux calls "standard line discipline".

void setup(){}
void draw(){}

void keyPressed(){
  println(key); 
}

Why is hair so hard to make behave well?

Announcements

  • Project 6 Optional
  • July 29 Deadline
  • July 26 and 29 Attendance
  • Topic Class Poll

Button Class Demo

Image-Based Animation

We can also just load and display a bunch of images!

These images can be hand-drawn (as in the case of flipbook animations) or created in animation programs like After Effects or Flash

The core of how old 2D (and even early 3D games) were animated.

Loading Animations in Processing

Same principle as loading a single image into a PImage, but now we need multiple of them!

Load images into an array, storing them in animation order.

But uh...

PImage animation[100];
animation[0] = loadImage("anim-0.png");
animation[1] = loadImage("anim-1.png");
animation[2] = loadImage("anim-2.png");
// Yuck

Image Animations in Processing

The nf() function formats a number into a string. This is a convenient way to avoid having to hardcode image names.

nf() can also zero-pad numbers, which is great for keeping the frames in sorted order e.g. in a file browser.

To play the animation, loop over the animation array.

Can use the modulus operator to wrap the animation.

Processing has a global variable frameCount that auto-increments every time draw() is called.

Sprite Sheets

Hands-On: Sprites

  1. Download the Megaman sprite set from Canvas (or find your own set of sprites that you'd like to use).
  2. Within setup(), load these images into an array. Use a loop (potentially with nf()) instead of manually loading images one-by-one.
  3. Within the draw() function, display the images in sequence at a given location
  4. Use frameCount and the modulus operator to make the sprite loop infinitely.
  5. Experiment with frameRate() to change the speed of the animation. Use one you think looks good.

Timers

We tied our sprite animation speed to the frame rate.

 

This isn't always a good idea. In fact, I'm going to go ahead and say that it's a bad lazy idea, even though it's convenient and everyone does it.

Timers

Instead of tying ourselves to the draw rate (i.e. do something every draw), we can look at a clock, and only take action if it has been enough time since the last time it happened.

Example for Sonic:

We want to advance the animation every 0.2 seconds (200ms).

 

Advance the frame if it has been at least 200ms since the frame was last advanced.

int animationTimer = 0;
int animationTimerValue = 200;
int currentFrame = 0;
void draw() {
  image(x_sprite[currentFrame], 20, 250);
  // If it has been more than 200ms since the last "tick"
  if ((millis() - animationTimer) >= animationTimerValue) {
    currentFrame = (currentFrame + 1) % numFrames;
    // Set time of current tick
    animationTimer = millis();
  }
}

We can use millis() to read how many milliseconds have passed since the program started

Hands-On: Timers

  1. Experiment with the code example for a timer-based sprite
  2. Turn this into a Timer class, which has an interval for activation and has a method which returns whether it's been long enough since it was last activated.
  3. Add a method to pause your timer.
  4. Use the Timer class to animate your sprite. Pause/unpause your timer when the user clicks, so that the user can pause your animation by clicking.

Final Project Planning

Index Cards!

  1. Your name and EID.
     
  2. One thing that you learned from class today. You are allowed to say "nothing" if you didn't learn anything.
     
  3. One question you have about something covered in class today. You may not respond "nothing".
     
  4. (Optional) Any other comments/questions/thoughts about today's class.