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.
Processing runs under what Linux calls "standard line discipline".
void setup(){}
void draw(){}
void keyPressed(){
println(key);
}
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.
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
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.
setup()
, load these images into an array. Use a loop (potentially with nf()
) instead of manually loading images one-by-one.draw()
function, display the images in sequence at a given locationframeCount
and the modulus operator to make the sprite loop infinitely.frameRate()
to change the speed of the animation. Use one you think looks good.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.
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();
}
}
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.