Independent Model Rate

Independent Model Rate

This section describes a method of programming incremental animation that gives two advantages:

  • frame-rate independence for incremental animation
  • high model rates for normal (<100 fps) movie frame rates. High model rates make some incremental algorithms function more accurately.

This demo gives the Collision Using Spring Force demo an independent model rate.

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

on exitframe()
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.

property modelFPS
property millis
property instanceList

on new(me, mfps)
instanceList = []
modelFPS = mfps
millis = the milliseconds
(the actorlist).append(me)
return me
end

on stepframe()
elapsed = the milliseconds – millis
mframes = integer(modelFPS * (elapsed / 1000.0))
doModelFrames(mframes)
if modelFPS > 0 then
millis = millis + (mframes / float(modelFPS)) * 1000
end if
end

on doModelFrames(mframes)
repeat with mf = 1 to 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.

Leave a Reply

Your email address will not be published. Required fields are marked *