Animation

In the lesson on interaction, we learned how to move shapes, change their size and change their color, reacting to user input. These changes can also be automated without user input, or animated.

Let's start with a simple shape.

function draw() { background(220); ellipse(100, 100, 100); }

If we want to animate the shape across the screen, we need to change the point where it's being drawn from over time.

It's easy to change the point by using a mouse click or mapping it to the mouse position, but how can we change it without the mouse?

To start, we need a variable to use for the shape position.

var x = 100; function draw() { background(220); ellipse(100, 100, 100); }

Now all we have to do is increment the variable.

var x = 100; function draw() { background(220); ellipse(x, 100, 100); x++; }

Why does it look like the circle is moving?

Hint: take out the background and see what happens.

How would I make it go faster?

var x = 100; function draw() { background(220); ellipse(x, 100, 100); x += 5; }

That's cool, but our circle is flying off the screen!

Let's use a conditional statement to make it loop back to the beginning.

var x = 100; function draw() { background(220); ellipse(x, 100, 100); x += 2; if (x > width) { x = 0; } }

Why does the circle suddenly disappear on the right side? How could we change the conditional to make sure the circle gets all the way off the screen?

Can we also change the y position?

var x = 100; var y = 100; function draw() { background(220); ellipse(x, y, 100); x += 2; y += 2; if (x > width) { x = 0; } if (y > height) { y = 0; } }

Why does the circle loop on the y axis before the x axis?

Let's try animating the size too.

var x = 100; var y = 100; var s = 100; // size function draw() { background(220); ellipse(x, y, s); x += 2; y += 2; s += 2; if (x > width) { x = 0; } if (y > height) { y = 0; } }

Speed

Instead of looping around the canvs, what if we want the circle to bounce back and forth like a ball?

So far we have been using a hard coded number to change the values of x and y.

What if we used a variable instead? We could then update that variable given certain conditins, like reaching the end of the canvas.

We'll start with a speed variable.

var x = 100; var speed = 5; function draw() { background(220); ellipse(x, 100, 100); x += speed; if (x > width) { x = 0; } }

In the above sketch, we can change the speed value to change how fast x moves.

Next, we can reverse the speed instead of resetting x.

There are two conditions that we want to check for, if the x position gets to the right side of the canvas, or back to the left. We can use a compound conditional here.

Then we will use simple math to make speed the opposite value.

var x = 100; var speed = 5; function draw() { background(220); ellipse(x, 100, 100); x += speed; if (x > width || x < 0) { speed *= -1; } }

This only works because speed is a variable that can be changed or updated during the lifetime of the program.

Try adding a speed variable for y to make the ball bounce off all four sides of the canvas.

Randomness

The previous examples all have smooth movement. If we want to create more natural or unpredictable animation, to add a lifelike quality, one way to achieve that is to introduce randomness into the sketch.

The random function in p5 let's us generate random numbers.

var x = 100; var y = 100; function draw() { background(220); ellipse(x, y, 100); x += random(-5, 5); y += random(-5, 5); }

The random function takes one or two arguments, used to create a range. With two arguments, the smaller number will be the minimum, such as the -5 above, and the larger will be the maximum value of the number generated. With one argument, 0 will be one end of the range, the other end will be the argument added.

Try playing with the arguments in the above example to see how the random behavior changes.

What if the x values have a range of 0 to 5? What about -5 to 0?

Color

Changing color over time also requires using variables to represent color values.

var r = 0; var c = 1; // change function draw() { background(220); fill(r, 0, 100); noStroke(); ellipse(width/2, height/2, 200); r += c; if (r > 255 || r < 0) { c *= -1; } }

Using random to generate color.

function draw() { background(220); var r = random(255); var g = random(255); var b = random(255); fill(r, g, b); noStroke(); ellipse(width/2, height/2, 200); }

That's cool, but it's a little crazy. What if we wanted to change the color only once every 30 frames?

Modulo

JavaScript includes a mathematical operator called modulo % which gives the remainder of a division of two values. Let's look at some examples in the console.

10 % 9;
5 % 4;
2 % 1;
1 % 2;
30 % 3;
31 % 3;

Because of this behavior, modulo is useful for counting a repeated range.

function setup() { createCanvas(300, 100); textSize(20); textFont('menlo'); frameRate(2); } function draw() { background(220); text('frameCount', 10, 40); text('frameCount % 10', 10, 80); text(frameCount, 240, 40); text(frameCount % 10, 240, 80); }

Notice that when we count up using modulo, we repeat the same count, even though i keeps going up.

We can use that with the frameCount in p5 to tell how many time we've gone a certain number of frames.

We need to make our color values global, and then change them whenever the frameCount remainder of 30 is 0 (this will happen at 30, 60, 90, 120...)

var r, g, b; function setup() { createCanvas(640, 360); r = random(0,255); g = random(0,255); b = random(0,255); noStroke(); } function draw() { background(220); if (frameCount % 30 === 0) { r = random(0,255); g = random(0,255); b = random(0,255); } fill(r, g, b); ellipse(width/2, height/2, 200); }

Let's visualize frameCount.

function setup() { createCanvas(640, 200); textFont('menlo'); textSize(20); } function draw() { background(220); text('frameCount', 10, 40); rect(frameCount, 50, 50, 40); text(frameCount, frameCount, 80); var mod = 30; text('frameCount % ' + mod, 10, 120); rect(frameCount % mod, 130, 50, 40); text(frameCount % mod, frameCount % mod, 160); }

What else can we animate with frameCount, %, random() and our shapes?

Try position, size, color, speed or other factors.