Skip to content
Mar 13 2010 / alecmce

Ordering ENTER_FRAME events

About ENTER_FRAME

If you create multiple listeners to one event, then the listener methods run in their priority order (or if priority doesn’t differentiate, in the order that they were registered to the event).

If you create a listener for an ENTER_FRAMEon a display object, then it dispatches ENTER_FRAME each frame.

When an ENTER_FRAME listener is created for an object, the object is added to the end of a list of objects that need to dispatch ENTER_FRAME. It doesn’t matter what the relationship between the objects are, the ENTER_FRAME listeners of whichever object was added to that list first fire before objects later in the list.

Maybe that’s obvious to you; I don’t find it obvious. Without thinking about it, I want a high-priority listener to run before a low priority listener, irrespective of the objects to which they are listening. At least intuitively, I think of ENTER_FRAME as a universal event, rather than emanating separately from each object.

The Problem

The difficulty with this is that I cannot control the order in which ENTER_FRAME calls happen over an application. I can’t, for example, create an ENTER_FRAME listener for a Sprite and make sure that it runs before any other existing ENTER_FRAME listener across the application. I can make sure that for the particular Sprite it runs first by using priority, but the only way I can re-order the objects that dispatch ENTER_FRAME is by temporarily removing (and subsequently re-applying) every listener for each object ahead of it in the list

For RacetrackStats, a project that I am currently working on which attempts to measure the time that it takes to execute code and to render the screen, I want to be able to ‘get in first’ and ensure that a particular ENTER_FRAME listener is the first method that runs in an ENTER_FRAME cycle. The only way I can do this is by telling the developer who uses the RacetrackStats library to construct the RacetrackStats instance before doing anything else, and then keeping an ENTER_FRAME listener registered from that point onwards, even if the stats package is not on the stage and not being used.

Most of the time this isn’t a big deal. Normally the function of an ENTER_FRAME listener in an object is internal to that object, so a conflict between the code running in two different objects’ ENTER_FRAME listeners is unlikely.

Tickers and Signals

The most simple solution to this problem – if it is a problem – is to use only one object to dispatch ENTER_FRAME events. If you use some form of dependency injection like Swiz or RobotLegs this can be done relatively painlessly, since you can inject the dispatching object wherever it’s required. Then, you can use priority to determine the order in which listener methods run.

A related solution might be to use a Ticker; essentially to have only one ENTER_FRAME listener which iterates through a collection of methods that you subscribe to it and runs those in order. The linked example is a very simple Ticker, but more complex functionality like priorities would be relatively easy to add.

Similarly, you could use as3-signals and wrap the stage’s ENTER_FRAME into a native signal event. This would give you all the functionality you are likely to want ‘out of the box’. If you feel like you need to have a greater level of control over your ENTER_FRAME, this is probably the way to go. This is my preferred solution – at the moment!

Example

Hopefully the description demonstrates what I mean. If you’d like a more concrete demonstration, then you can build this file and inspect it’s output:

http://gist.github.com/331534

  • http://noiseandheat.com/ mnem

    The ENTER_FRAME thing has always been a bit shoddy, IMO. Perhaps at one point they considered each object being able to run at different frame rates. Flash with more race conditions – mmm.

    One thing about the potential issue with RacetrackStats (lovely improvement on the original incidentally) – surely it doesn’t matter that it’s ENTER_FRAME listener is called first, only that it is called once per application frame? I thought that it was displaying the relative time difference between now and now – 1 frame, more or less? So, the first frame, if you don’t get called first, will be short, but subsequent frames will have valid measurements?

    • http://alecmce.com Alec McEachran

      RacetrackStats has someway to go before it really improves on the original, but thanks. :)

      I don’t agree though that being first is unimportant. I want to differentiate between time that’s taken up by code, and time that’s taken up by rendering. If code executes before my ENTER_FRAME, I can’t differentiate it from the render part. The frame-rate and a sense of the overall load would be preserved, but the code-render separation would be screwed up.

      • http://noiseandheat.com/ mnem

        Ah-hah, that’s a very good point, I hadn’t considered that.

        I don’t know the answer to this (and I’m too tired to knock up a test just now :) , but do you know if code copies pixels from one bitmap to another, would that be picked up as render load or code load?

        • http://alecmce.com Alec McEachran

          Of the top of my head, I’d guess that copying pixels between bitmaps and bitmapdata is simply data shuffling, so is part of the code process, whereas the render process is the actual composition of the display list information into the screen buffer. But meh, I’m only guessing, which relies on logic, and the Flash Player defies logic more often than not.

          • http://noiseandheat.com/ mnem

            That seems sane, but as you say, Flash logic can be, uh, interesting.

            I’ll check it out tomorrow when my sleep patterns are a little more normal.

  • http://noiseandheat.com/ mnem

    The ENTER_FRAME thing has always been a bit shoddy, IMO. Perhaps at one point they considered each object being able to run at different frame rates. Flash with more race conditions – mmm.

    One thing about the potential issue with RacetrackStats (lovely improvement on the original incidentally) – surely it doesn't matter that it's ENTER_FRAME listener is called first, only that it is called once per application frame? I thought that it was displaying the relative time difference between now and now – 1 frame, more or less? So, the first frame, if you don't get called first, will be short, but subsequent frames will have valid measurements?

  • http://alecmce.com alecmce

    RacetrackStats has someway to go before it really improves on the original, but thanks. :)

    I don't agree though that being first is unimportant. I want to differentiate between time that's taken up by code, and time that's taken up by rendering. If code executes before my ENTER_FRAME, I can't differentiate it from the render part. The frame-rate and a sense of the overall load would be preserved, but the code-render separation would be screwed up.

  • http://noiseandheat.com/ mnem

    Ah-hah, that's a very good point, I hadn't considered that.

    I don't know the answer to this (and I'm too tired to knock up a test just now :) , but do you know if code copies pixels from one bitmap to another, would that be picked up as render load or code load?

  • http://alecmce.com alecmce

    Of the top of my head, I'd guess that copying pixels between bitmaps and bitmapdata is simply data shuffling, so is part of the code process, whereas the render process is the actual composition of the display list information into the screen buffer. But meh, I'm only guessing, which relies on logic, and the Flash Player defies logic more often than not.

  • http://noiseandheat.com/ mnem

    That seems sane, but as you say, Flash logic can be, uh, interesting.

    I'll check it out tomorrow when my sleep patterns are a little more normal.