Stuck For It

After a little tinkering, I made a nasty little discovery. It seems that if you have a MovieClip embedded in a MovieClip, that unlike scaling and rotating, operating on the top-level MovieClip animation (stop, gotoAndStop, etc.) doesn’t operate on the lower-level MovieClip animations, which merrily go on with whatever default animation they had running.

When I tell a piece of art to stop or go to a particular frame, I mean ALL of it, not just the top-level container that has all the other stuff re-used inside of it.

I won’t ultimately have control over what the artists do with the MovieClips they attempt to animate (and don’t have patience to ‘reorganize’ everything that they do). I have never in 18 years of professional game development encountered an artist that could follow technical direction, and don’t plan on meeting the first one any time soon.

Anyway, I recursively dispatch/invoke the commands on the top-level object, and assume that the lower level objects all have the same number of frames. I will most likely have to add some code to the top-level object for better animation/scaling control at runtime, but that’s a different fish to fry.

Does anybody have any better ideas than this to ‘fix’ it?

A static, global one that just invokes the built-in commands, whatever they are.


        /**
         * Recursively invoke a MovieClip function on top-level and all of its 
         * children.  Works around a BUG where invoking stop or gotoAndStop or 
         * whatever will affect the parent, and no children.  They all continue 
         * animating at whatever frame rate the game is running at.
         *
         * @param obj Top level MovieClip
         * @param strFunc Function name to invoke
         * @param args 0 or more arguments to pass to the function 
        **/
        public static function IterateMovieClips(obj:*, strFunc:String, ... args ):void
        {
            IterateMovieClipsArray(obj, strFunc, args );
        }
        
        /**
         * Invoke function on MovieClips
         * @param obj Top level MovieClip
         * @param strFunc Function name to invoke
         * @param args Array of arguments to pass to the function
        **/
        public static function IterateMovieClipsArray(obj:*, strFunc:String, args:Array ):void
        {
            if( obj is MovieClip )
                obj[strFunc].apply(obj, args);
            var icurr:int = obj.numChildren;
            var curr:DisplayObject;
            while( icurr-- )
            {
                curr = obj.getChildAt(icurr);
                if( curr is DisplayObjectContainer )
                    IterateMovieClipsArray(curr as DisplayObjectContainer,strFunc,args);
            }
        }

Or this one in a Sprite (DisplayObjectContainer) derived things that receives a function belonging to the top-level one…


        /**
         * Invoke a function from this class on each Child of this 
         * @param func Function to invoke on each member
         * @param ... args Things to pass into func
        **/
        protected final function OnEachMovieClip( func:Function /* obj,args */, ... args ):void
        {
            OnEachMovieClipA( func, this, args );
        }

        /**
         * Invoke a function from this class on each Child of obj
         * @param func Function to invoke on each member
         * @param args Array of things to pass into func
        **/
        protected final function OnEachMovieClipA( func:Function, obj:*, args:Array ):void
        {
            var curr:*;
            if( obj is MovieClip )
            {
                args.unshift(obj);
                func.apply( this, args );
                args.shift();
            }
            var icurr:int = obj.numChildren;
            while( icurr-- )
            {
                curr = obj.getChildAt(icurr);
                if( curr is DisplayObjectContainer )
                    OnEachMovieClipA(func,curr,args);
            }
        }

Another little problem: I’ve discovered some odd stability issues in AS3 when I add and remove children at runtime from a DisplayObjectContainer type. It leaks memory (according to stats in the Task Manager) like a sieve and eventually Flash interpreter its self crashes out. It seems like there are some stray internal references to ‘this and that’ in the DisplayObject hierarchy that don’t get resolved well when hundreds of things are dynamically allocated and dereferenced. I worked around it by keeping DisplayObject data around, so they didn’t get dereferenced at render time, and the leaking/crashing stopped happening. It’s annoying, but I suppose I’m stuck with it that way.