Animation

To be moved by that which does not move

An animation is a series of still pictures shown so quickly that they look like movement. Each picture is called a frame. Our programs can make animations by drawing a frame, showing it, and then repeating the process with a small change.

The Animation Loop

Every animation has the same three steps, repeated over and over.

  1. Clear the previous frame.
  2. Draw the new frame.
  3. Tick to show it and wait for the next one.
csp
You may also type <- !=>= <= for auto complete.

A square slides from the left side to the right. Here is what happens on each pass through the loop.

The variable x is created before the loop. As we learned in the scope chapter, a variable created inside a block disappears when the block ends. If x were created inside the loop, it would be reset every frame, and nothing would move.

Why clear screen? Try deleting the CLEAR_SCREEN() line from the example above. The square leaves a smear behind it.

The hidden drawing is not erased on its own. Everything we draw stays there until we clear it. Without CLEAR_SCREEN, each new square is drawn on top of all the old ones.

Clearing also removes any background we drew. This means a background has to be drawn again every frame, right after clearing.

csp
You may also type <- !=>= <= for auto complete.

Frames per Second

The number given to CLOCK_TICK is the number of frames per second, often shortened to FPS. CLOCK_TICK(60) shows 60 frames every second. Each frame lasts about 17 milliseconds.

CLOCK_TICK is smart about waiting. If drawing a frame took 5 milliseconds, it only waits for the rest of the frame. That keeps the speed steady, even when some frames have more to draw than others.

Our square moves one pixel per frame, so at 60 FPS it moves 60 pixels per second. To cross the canvas takes a little under 7 seconds.

This leads to an important point. Speed is measured per frame, not per second. If we change CLOCK_TICK(60) to CLOCK_TICK(30), the square still moves one pixel per frame, but there are half as many frames, so it moves half as fast. Try it.

csp
You may also type <- !=>= <= for auto complete.

Fewer frames per second also makes motion look choppier. Most games use 60.

The FPS has to be bigger than zero. A program can also never run faster than its code allows. If a frame has too much to draw, CLOCK_TICK cannot make up the lost time.

Velocity

Instead of adding a fixed number, it is common to keep the speed in its own variable. We call it velocity. This lets us change how an object moves without changing the rest of the code.

csp
You may also type <- !=>= <= for auto complete.

Change speed to 6 and the square moves twice as far in the same time. A negative velocity moves in the opposite direction. Since CSP has no negative sign in front of a variable, we write 0 - speed to flip it.

Bouncing

With a velocity variable and an IF, we can make an object bounce off the walls.

csp
You may also type <- !=>= <= for auto complete.

The square is 40 pixels wide, so its right edge touches the wall when x is 360. When it gets there, we put it exactly on the wall and flip the sign of speed. Positive speed becomes negative, and the square turns around.

This animation uses REPEAT UNTIL false, so it never ends on its own. Typically a loop in CSP stops after 100,000 iterations. At 60 frames per second, that is about 28 minutes before the program stops with an error. This is not the case when CLOCK_TICK(n) is called though. Each time CLOCK_TICK(n) is called, the iteration limit is increased by one, allowing REPEAT UNTIL false to run forever.

Gravity

Real objects speed up as they fall. We can copy this by changing the velocity itself every frame. Here is a ball dropping and bouncing on the floor.

csp
You may also type <- !=>= <= for auto complete.

Each frame, gravity changes the velocity, and the velocity changes the position. That chain is the key idea behind motion in games. The ball is 20 pixels in radius, so its bottom touches the floor at y = 380. When it lands, we flip its velocity and multiply it by 0.9, so each bounce is a bit smaller.

Counting Frames

Sometimes we want something to happen on a schedule. We can keep a counter that goes up by one every frame, and use MOD to make a repeating pattern.

csp
You may also type <- !=>= <= for auto complete.

frame MOD 60 counts from 0 to 59 and starts again, so it repeats once per second at 60 FPS. The circle is drawn for the first half of every second, which makes it blink.

Practice


Next: Drawing Many Things