The Model
The variables used in an incremental animation—position,
velocity, etc of a set of objects—along with the algorithm
that makes them interact is called a model. At any point
in time the variables store the state of the model.
The model is separate from what appears on screen,
which is merely a visual representation of the state
of the model. Usually they are so closely related that they might seem
like the same thing. However, the model can execute just fine without
ever showing a representation of it on screen. The position and velocity
variables would still go through their various values,
depending on the model algorithm, even if the sprite properties are never
set accordingly.
The act of creating a visual representation of a model
is called rendering. To set sprite and cast member properties
based on a model is a form of rendering.
Model Rate
Each time a model algorithm is executed, updating the state of the model,
it is one iteration, or step. I'll call
this a "model frame" in keeping with Director
terminology. So the number of model frames per second is the "model
frame rate" or just "model rate".
So far in the incremental animation demos, the model
rate has been tied to the movie frame rate because the model
algorithm was executed once per movie frame, in the exitframe
handler.
In this demo those two rates are separated. The script
below shows the form of the standard behavior script with a slight
modification made to provide the rate separation.
global modelRateObj
property sp -- and other properties declared
on beginsprite(me)
sp = sprite(me.spritenum) -- and other variables initialized
modelRateObj.addInstance(me) end
on modelFrame(me) -- perform incremental animation
algorithm end
onexitframe()
sp.loch = x
sp.locv = y -- and other sprite properties set end
Sprite behavior showing separation of movie
and model rates
The primary difference is that the model
algorithm has been moved out of the exitframe handler and into a 'modelFrame'
handler. Now the model algorithm can be executed independent of
the frame rate of the movie. The only statements left in the
exitframe handler are those that render the model.
All that is left to do is call the modelFrame handler
of each object however many times per second is desired. For correct function
of the collision model it is necessary that the objects' modelFrame handlers
are called in step with each other.
In this demo this is done by a script I've named modelRate,
which is instantiated when
the movie starts.
on new(me,
mfps)
instanceList = []
modelFPS = mfps
millis = themilliseconds
(theactorlist).append(me) return me end
onstepframe()
elapsed = themilliseconds
- millis
mframes = integer(modelFPS
* (elapsed / 1000.0))
doModelFrames(mframes) if modelFPS > 0then
millis = millis + (mframes / float(modelFPS))
* 1000 end if
end
on doModelFrames(mframes) repeat with mf = 1to mframes repeat with instance
in instanceList
instance.modelFrame() end repeat
end repeat
end
on addInstance(me,
inst)
instanceList.append(inst) end
script "modelRate" - an
explanation of "the actorlist" is given here
modelRate maintains a list of script instances,
and it calls the modelFrame handler of those instances so many times per
second. It is the responsibility of each object in the model to register
itself with modelRate by passing a reference to itself
to modelRate's addInstance handler. This was shown in
the behavior script above, with the statement modelRateObj.addInstance(me).
When modelRate is instantiated, the desired model frame
rate is passed to the new() handler. After instantiation,
the model frame rate is adjusted by changing modelRate's modelFPS
property.
The function of this modelRate object is very similar to
Director's use of the actorlist, except it calls modelFrame()
so many times per second where stepframe() is called
once per frame. modelRate could be written to be based on the
frame rate and call modelFrame() so many times per movie frame.
One point about the line millis = millis + (mframes
/ float(modelFPS)) * 1000. Usually this is just a reset of millis
with millis = the milliseconds. The way it is reset here
compensates for the rounding done to get mframes, so the resulting model
rate is correct.
Biased Slider Drivers
This part is related to the material in the parametric
animation section.
The sliders in this demo are programmed as parametric
animation drivers. The parameters they provide are then biased,
using a bias-out function. Notice that when the model
rate slider sits at the middle of its range its value is 500,
even though the slider goes from 0 to 2000. By biasing
the parameter, finer adjustments can be made at the lower end of the range
(at the expense of adjustment at the high end). For finer adjustment at
the higher end, a bias-in function would be used.
There are two scripts attached to each of the sliders.
One provides the driver function p(), and the standard
slider driver code. The other script gets the value returned
by p() and uses it to set properties and variables
specific to this demo. This maintains the modularity
of the scripts.