...or anything else in the program environment
that can go through a range of values at run-time.
Whatever the driver is, in parametric animation its range
is shifted & scaled to p:0->1.
After that, p drives the animation of the properties
as described previously.
So for the driver function, p:0->1
is the target range. For a function that drives a property,
p:0->1 is the source range.
To illustrate, this demo gives a choice
of drivers for p—slider loch, mouse locv,
elapsed time, elapsed frames, and number of characters in a field. For
each driver in the demo, a function is created to shift & scale its
range to p:0->1.
Again, the general form for shifting & scaling driv:A->B
>> p:C->D is
p = (driv - A) * (D -
C)/(B - A) + C
If p (target range) is standardized to
0->1, making C = 0 and D
= 1, the equation becomes:
p = (driv - A) / (B -
A)
So, driver ranges and the functions for shifting &
scaling them to p:0->1:
Functions p = (sliderLoch - 28) / (166 - 28)
p = (mouseLocv - 0) / (stageHeight - 0)
p = (elapsedTime - 0) / (2000 - 0)
p = (elapsedFrames - 0) / (100 - 0)
p = (characters - 0) / (20 - 0)
When doing these divisions in lingo, remember to make
at least one of the operands a float. This is explained in Integer
Division.
Then p drives the properties that are
animated. In this demo they are the sprite loch, locv, and rotation properties.
The ranges for the properties and the functions that will shift &
scale p:0 ->1 to them:
onexitframe() -- drive p case driver of #slider: p = (spSlid.loch
- 28) / (166.0
- 28) #mouse:
p = (themousev) / float((thestage).rect.height) #time: p = eTime(2000) #frames: p =
eFrames(100) #chars: p
= charInput(20) end case
-- p drives animation
sp.loch = p * (478
- 203) + 203
sp.locv = p * (237
- 41) + 41
sp.rotation= p * (45
- 180)
+ 180 end
on eTime(max) return (themilliseconds mod max) / float(max) --
0->1 end
on eFrames(max)
frames = frames + 1 return (frames mod max)
/ float(max)
-- 0->1 end
on charInput(max)
ch = member("input").chars.count if ch > max
then ch = max --
limit return ch / float(max)
--
0->1 end
Some of the driver functions are right in the exitframe
handler, and some have been moved out, such
as eTime() and eFrames(). Drivers that are more complex should be moved
out for code clarity and reusability.
The mod operator used in the time- and
frame-based drivers has the effect of 'wrapping' those
values. It returns the remainder after dividing the second argument into
the first.
Frame-rate Independence
When the animation is driven by "elapsed time",
the animation is called "time-based" or "frame-rate
independent". This means the animation will have the same
pace regardless of the frame rate of the movie or the speed of
the computer it is played on. Notice the difference between elapsed
frames and elapsed time when playing at slow
frame rates. If the computer your animation plays on can't keep up with
the frame rate of your movie, it will be playing at a lower frame rate.
Exceeding the Range
In this demo, when 'mouse locv' is selected the animation
is not limited to the specified range, because mouse locv generates values
outside of 0->stageHeight. This illustrates the fact that the
end points of the ranges merely served as points
of reference in creating the linear function, and did not
limit the values to those ranges. Where is the arrow when the
mouse is at the bottom edge of the stage?
Limiting can be done in different places. You could limit
the range of the driver, before converting to p.
You could limit p to 0->1. Or you could limit the
range of the property after converting from p.
Standard limiting statements:
if var > max then var = max
if var < min then var = min
With the other drivers in the demo, the limit is
in the driver (in other words, before converting to p).
This is the logical place for limiting, but there may be exceptions.
Modularity
Because the parameter is standardized to p:0->1, the
code can be divided into reuseable pieces. For example,
you could use the eTime() function from this demo to
make any parametric animation time-based.
•How would you write an eTimeBF() driver
that goes back and forth between 0 and 1 instead
of wrapping to 0 like the one in the demo?