views:

110

answers:

2

Recently I took on a rather daunting task of creating an interactive music video for the popular show Ghost Whisperer. I was brought in late in the project and was confronted with a giant authoring file (some 5000+ frames long). The previous programmer (who did everything in AS2) had essentially embedded a two and half minute FLV on the time main time line and at certain frame points would add in clips for interactivity with basic mouse click functionality that would trigger those clips to play other clips with some flash elements and some video elements.

(the final version I created can be viewed here http://www.gwghostmagic.com);

Being a neat freak I decided to rebuild the whole thing in AS3, ditch the time line altogether and rather load in my elements at run time so that instead of 5000 frames I had one frame and to trigger the actions added an Event.ENTER_FRAME event listener to trigger the interactivity when the loaded .swf would reach certain frames. From a programmers stand point it made everything much clearer and easier to manipulate certain actions. The problem was, the thing ran like crap.

The 5000+ frame version loaded faster and ran smoother than my AS3 version. Which brings me to the question, when is it better to embed and run off the time line than run off of an event listener? Is flash better suited for time line functionality?

Initially I decided to build and run off of a streaming .flv but syncing up the actions to the .flv was impossible because the .flv was running at 23.975 fps whereas my flash movie was running at 24 fps. Alas I was forced to compile an .swf with the flv embedded. That .swf was then loaded into my main .swf that contained all the functions and extra clips that would play according to the loaded .swf's frame position.

One thing I've noticed is that the Event.ENTER_FRAME seems to slow the whole damn application down because at every frame it has to run down a list of if statements 200 lines of code long. Wherein if the whole thing was embedded I might only need to insert a keyframe where the interactive clip would be instantiated and then would know immediately what to do, rather than cycle through if else statements.

Did I screw up trying to make things nice and tidy? Is it better to let flash be flash? Should I seek out another career? Any input is greatly appreciated.

+1  A: 

I think that having the event trigger every frame as opposed to only triggering actions occasionally accounts for the performance difference. Hopefully you could minimize the amount of code and conditionals that was run through in the event handler.

Here's an idea I haven't tested:

var dispatch:Object = {
  f1:   function () {textBubble.text = "This is Rush Hour 2";},
  f61:  function () {textBubble.text = "";},
  f111: function () {textBubble.text = "This scene has 50 takes; "
                     +"Jackie Chan said \"Square Madison\" each time.";},
  f171: function () {textBubble.text = "";}
};
addEventListener(Event.ENTER_FRAME, function (e:event) {
  if (dispatch["f"+e.target.currentFrame] is Function) {
        dispatch["f"+e.target.currentFrame]();
  }
});

This uses the Object as an Associative Array as described in the live docs.

dlamblin
Here I'm assumig I would declare dispatch as an Object variable?
Jascha
Yeah, I didn't typecast it. I guess I do more in JavaScript than in ActionScript lately. I fixed that and deleted a stray comma.
dlamblin
+1  A: 

You are probably correct - running 200+ lines of code on every frame is slowing you down. Instead of a huge list of statements, split your frame functions up and only call the ones you need - this is an expansion on dlamblin's idea - this way you are running the smallest amount of code necessary for each frame:

function doThisOnFrame20():void
{
    //do stuff...
}

function doThisOnFrame50():void
{
    //do stuff...
}

var frameFunctions:Array = new Array();
frameFunctions[20] = doThisOnFrame20;
frameFunctions[50] = doThisOnFrame50;

function enterFrameListener(event:Event):void
{
    if(frameFunctions[swfWithFLV.currentFrame] is Function)
    {
        frameFunctions[swfWithFLV.currentFrame]();
    }
}

addEventListener(Event.ENTER_FRAME,enterFrameListener);
Reuben