Animation and Keyboard
Velocity and Elapsed Time in a Simulation
Here is another variation of this program.
This time, the cursor keys will be used to change the velocity of the ball (the
speed of the ball, in other words). The velocity will be stored in a variable
named v
, and in the beginning it equals 0. The velocity represents how much
the position of the ball changes on each iteration of the while
loop.
So, if the velocity equals 3, the ball will move 3 pixels to the right on each
iteration of the while
loop.
int x = SCREEN_W/2; int v = 0; while (!key[KEY_ESC]) { if (key[KEY_LEFT]) v--; if (key[KEY_RIGHT]) v++; x += v; clear_to_color(surface,makecol(255,255,255)); circlefill(surface,x,200,50,makecol(0,0,255)); blit(surface, screen,0,0,0,0,SCREEN_W,SCREEN_H); rest(20); } return 0;
Let us consider this question: what
is the actual speed of the blue ball? We said that the ball moves by a number
of pixels given by variable v
on every iteration, but how long does each iteration take?
We can certainly say that an iteration takes longer than 20 milliseconds, since the program is ordered to rest for 20 milliseconds on every iteration. Still, how much time do the other statements take to execute?
The clear_to_color
and blit
statements will take some non-negligible amount of time, since they have to process the entire drawing surface containing almost half a million pixels, where each pixel needs to be processed separately. The amount of time it takes depends on the speed of the computer executing the program. The only correct answer would be that the exact duration cannot be known in advance.
Try changing the argument of the rest
function to observe the slowdown or speedup that may affect other computers.
However, the exact time of an iteration can
be measured. Remember that the time at present, also called the current time,
can always be obtained from the variable tickCount
. In order to measure the duration of an iteration, all the program needs to do is to store, in a variable, the start time of previous iteration (measured in ticks). Then, to compute duration of previous iteration, measured in ticks, the program needs to subtract the start time of the previous iteration from the start time of current iteration which is equal to the time at present. It should then update the variable that stores the previous start time to reflect the time at present. Here is the code:
int previousTime = tickCount; double x = SCREEN_W/2; double v = 0; while (!key[KEY_ESC]) { int elapsedTimeInTicks = tickCount - previousTime; previousTime += elapsedTimeInTicks; if (key[KEY_LEFT]) v -= 30; if (key[KEY_RIGHT]) v += 30; x += v*elapsedTimeInTicks/1000.0; clear_to_color(surface, makecol(255,255,255)); circlefill(surface,x,200,50,makecol(0,0,255)); blit(surface, screen,0,0,0,0,SCREEN_W,SCREEN_H); rest(20); } return 0;
Notice that we had to make variables x
and v
to be of
type double
, as their values need to have precision higher than one pixel.
This program does pretty much the same thing as the previous one. However, the advantage of this program it that the ball will move at the same speed regardless of the speed of the computer running the program.
The variable v
now contains
the speed of the ball represented in pixels per second. The elapsedTimeInTicks
variable measures the elapsed time of one iteration. It is
calculated in the manner as previously described, by storing the current time
of an iteration into the variable previousTime
. The value of the
variable previousTime
will be used on the next iteration, when it will represent
the time of the previous iteration.
Remember that one tick equals one millisecond.
To calculate the elapsed time in seconds, the value of elapsedTimeInTicks
must be divided by 1000. The program then multiplies the elapsed
time (in seconds) by the velocity v
(in pixels per second) to get the distance
in pixels that the ball should be moved by. This is directly related to the
equation of movement with uniform velocity used in physics that says:
- x = x0 + vt
where x is the position at present, x0 is the previous position, v is the velocity and t is the elapsed time.
It was not a complete truth when we said
that this program would move the ball at the same speed regardless of the
computer running it. The previous program takes measures to ensure that the rate
of change of the variable x
is not affected by the speed of the machine that is executing the
program. This still does not take account of the rate of change of the variable
v
. On a faster machine, the variable v
will be
changed more often than on a slower machine because iterations on a faster
machine execute faster. To remedy this problem completely, a simple change will
be sufficient:
if (key[KEY_LEFT]) v -= elapsedTimeInTicks; if (key[KEY_RIGHT]) v += elapsedTimeInTicks;
Finally, we have made this program unaffected by the speed of the computer.