FRAME EVENTS
Event handlers called every frame in a Director movie
Every frame Director calls an number of handlers. To avoid script errors the order in which these handlers in called is important.
Where | Handler | When |
---|---|---|
movie | prepareMovie() | First frame of movie |
frame | new() + beginSprite() | First frame of sprite |
sprite(1..n) | new() + beginSprite() | First frame of sprite |
actorList[1..n] | stepFrame() | Every frame and updateStage() |
sprite(1..n) | prepareFrame() | Every frame |
frame | prepareFrame() | Every frame |
After display is updated | ||
movie | startMovie() | First frame of movie |
sprite(1..n) | enterFrame() | Every frame |
frame | enterFrame() | Every frame |
frame | idle() | Every frame |
sprite(1..n) | mouseWithin() | Every frame when mouse is over sprite |
sprite(1..n) | exitFrame() | Every frame |
frame | exitFrame() | Every frame |
movie | stopMovie() | Last frame of movie |
frame | endSprite() | Last frame of sprite |
sprite(1..n) | endSprite() | Last frame of sprite |
enterFrame()
It is better to use the enterFrame() handler to modify sprites than the prepareFrame() handler. The reason is that it is about 10% faster. I suspect that code in stepFrame() handlers is also slower than the enterFrame() handler but I have not tested it.
The drawback of the enterFrame() handler is that the display is updated before this hanlder is called. Normally this is only a problem in the first frame of a sprite. The problem can be fixed by calling the enterFrame() handler from the beginSprite() handler. As illustrated here:
on beginSprite me me.enterFrame() end on enterFrame me -- Animate end
There is one problem with this method. Sprites with a higher number than the current sprite may not be fully initialized when enterFrame() is called from beginSprite(). This can be fixed by moving the call to enterFrame() from beginSprite() to prepareFrame(). As illustrated here:
property pInitialized on prepareFrame me if not pInitialized then pInitialized = TRUE me.enterFrame() end if end on enterFrame me -- Animate end
Since prepareFrame() is called every frame this code run a little bit slower than calling enterFrame() from beginSprite(). Normally this will not be any problem at all.
mouseWithin()
This handler is called every frame as long as the mouse is over the sprite. If a sprite is only animating in this condition it is a good idea to move code from enterFrame() to mouseWithin().
stepFrame()
The stepFrame() handler was added to Director a very long time ago and it is not used a lot anymore. The prepareFrame() and enterFrame() handlers are used instead. The stepFrame() handler can be used to optimize the speed of Director movies by removing unnessary calls to prepareFrame() and enterFrame(). In this example stepFrame() is only called when the sprite is animating.
This optimazation benefits movies with many behaviors in the same frame, but is not relevant if there is only a few behaviors in the same frame.
property pChannel property pInside on beginSprite me pChannel = sprite(me.spriteNum) end on endSprite me removeStepFrame(me) end on stepFrame me if pInside then pChannel.blendLevel = max(pChannel.blendLevel - 10, 0) if pChannel.blendLevel = 0 then removeStepFrame(me) else pChannel.blendLevel = min(pChannel.blendLevel + 10, 255) if pChannel.blendLevel = 255 then removeStepFrame(me) end if end on mouseInside me pInside = TRUE addStepFrame(me) end on mouseOutside me pInside = FALSE addStepFrame(me) end on addStepFrame me -- Modifying the actorList inside a stepFrame() handler has some bad side effects. There -- is a work around this this, which is documented elsewhere. if not (the actorList).getPos(me) then (the actorList).add(me) end on removeStepFrame me -- Modifying the actorList inside a stepFrame() handler has some bad side effects. There -- is a work around this this, which is documented elsewhere. (the actorList).deleteOne(me) end
stopMovie()
The stopMovie() handler is not the last handler called when a movie stop. First the stopMovie() handler is called and then the endSprite() handlers for behaviors is called. So you must careful not to have code in the stopMovie() handler, that will cause code in the endSprite() handlers to fail.
on stopMovie -- Send endSprite() events sendSprite(0, #endSprite) sendAllSprites(#endSprite) -- Remove behaviors from all sprites, to prevent endSprite() events later sprite(0).scriptInstanceList = [] repeat with c = 1 to the lastChannel sprite(c).scriptInstanceList = [] sprite(c).visible = TRUE sprite(c).puppet = FALSE end repeat -- Clear the actorList the actorList = [] -- Call new stopMovie handler newStopMovie() -- Prevent code in calling handler to be executed. The may fix the bug -- described here www.killingmoon.com/director/bugs/quit_projector abort() end on newStopMovie -- Add clean up here... end