We can make the sketch animate by using time as an input. Modify y
so that it is a function of time (millis()
). This causes the sketch to animate.
void setup() {
size(600, 600);
}
void draw() {
background(100);
for (int i = 0; i < 20; i++) {
float x = 10 + 50 * i;
float y = map(sin(i + millis() / 100), -1, 1, 80, 120);
circle(x, y, 20);
}
}
Remember that the mathematical sin() function has an output range between -1.0 and 1.0, so we need to map it to some larger value range for the y’s so that we can see circles move. Thus, we use the map()
function.
Note: Now that the circles are drawn in a different position each time draw()
is called, it is important to clear the canvas (background(100)
) at the beginning of draw()
. Otherwise each circle will be drawn on top of all the circles drawn by previous calls to draw()
. In all the sketches so far we have drawn the background once in setup()
, and since all the circles were drawn at the same position, this was not detectable. Now, we have moved the call to background()
into draw()
.
Try this: Change the sketch to animate the size of the object, instead of its position. You can base your work on this sketch and a one in XXX.
The previous sketch uses time to drive one of the shape’s properties (its vertical position). Let’s use random()
instead.
void draw() {
background(100);
for (int i = 0; i < 20; i++) {
float x = 10 + 50 * i;
float y = random(80, 120);
circle(x, y, 20);
}
noLoop();
}
Note: There are three screenshots next to the code, to show that the random()
returns a different sequence of values, and therefore the sketch draws a different image, each time it is run.
The noLoop()
function prevents draw()
from being called more than once. Let’s see what would happen if we removed it.
void draw() {
background(100);
for (int i = 0; i < 20; i++) {
float x = 10 + 50 * i;
float y = random(80, 120);
circle(x, y, 20);
}
}
Aargh! Just as the previous sketch drew the circles at different positions each time it was run, this one draws them at different positions every frame.
What if we want to remember the position from frame to frame, so that we can draw the circles at the same position each time (or, move them in a more organized way that incorporates their previous position)?
In Processing, the way to remember things is to use a variable. A variable can hold a single value, but we want to remember several values: the vertical position of each circle. The trick is that the single value that the variables holds can be an array, which itself holds several values. Here’s what it looks like to use an array to hold the y values, inside draw()
.
void draw() {
background(100);
float ys[] = new float[20];
for (int i = 0; i < 20; i++) {
ys[i] = random(80, 120);
}
for (int i = 0; i < 20; i++) {
int x = 10 + 50 * i;
circle(x, ys[i], 20);
}
}
Note: Processing needs to know how many elements are in the array when it is created, thus we need to say new float[20]
, however there are ways to change the length of the array later if needed.
As you can see above, simply using an array as intermediary doesn’t help with the jitter if the array is still initialized on each call to draw()
. Each call to draw()
makes a new array, stores it in a new variable named ys
, and fills the array with a new set of random numbers.