2

I have this baffling problem with Flash AS3 that I have been attempting to solve for a long time. I have a notion that perhaps this is a bug with the flash player, but perhaps you can shed some insight.

I have a MovieClip in Flash that is a star for 10 frames, a circle for another 10, and then a square for another 10, after which it will gotoAndPlay(1), replaying the animation. This MovieClip extends an AS3 class I have called FlipClip.

FlipClip has a function in it called reverseClip. This function's purpose is to flip certain graphic children around an axis every time Flash launches the EXIT_FRAME event.

public function FlipClip()
    {
        //as soon as this is instantiated, add the eventListener
        addEventListener(Event.EXIT_FRAME,flipTheClip);
    }

    public function flipTheClip(e:Event)
    {

        trace("currentFrame = " + currentFrame);

        //for sake of simplicity, we will flip every child
        for (var i=0; i<numChildren; i++)
        {

            var targetClip = getChildAt(i);
            var axis = 10;

            //if the target child has not already been flipped...
            if (Math.abs(targetClip.scaleX) / targetClip.scaleX != -1)
            {

                //reverse the child's direction with scaleX and move based on the axis
                targetClip.scaleX *=  -1;
                var dist:Number = targetClip.x - axis;
                targetClip.x = axis - dist;

            }
        }
    }

The obvious outcome is that every time we exit a frame, all of the graphic elements are flipped horizontally around x=10, and every ten frames the shape of the MovieClip changes from a star, to a circle, to a square. Right?

Nope.

The MovieClip does successfully flip around that axis, but then a strange problem occurs. The animation stops. The MovieClip is stuck as an eternal star. And Flash doesn't even recognize that the animation has stopped, as we get this output over and over;

currentFrame = 1
currentFrame = 2
currentFrame = 3
currentFrame = 4
...
currentFrame = 30
currentFrame = 1

All the way up to 30, at which point it goes back to one. The clip is still playing, but somehow the graphic elements are not updating!

Is this a problem with the flash player? Is this a problem with the code? Any help is appreciated!

I've uploaded the files for the .fla and .as on dropbox. I'm still figuring out how to embed something like that, but for now I'm gonna hope this link works for you.

https://www.dropbox.com/sh/hcljutesblichpp/AABKQ4Kn8OTwfTaeh0I3nnOZa?dl=0

UPDATE:

If I convert every individual shape into a MovieClip within the parent MovieClip, it plays correctly. However, this is not very memory efficient or feasible with complex animations. Hopefully this bit of information can help you solve the problem.

theseal53
  • 189
  • 10
  • How does it transform from shape to shape? Can you share your .fla? That would be easiest I think. Sometimes when you modify object through code, it can override timeline stuffs. Why are you using EXIT_FRAME instead of ENTER_FRAME? You really need to learn how to use the semicolon, it's important. – BadFeelingAboutThis Aug 12 '15 at 19:09
  • *urk* HTML is not my strong point, and I'm not experience at all with sharing files online. I'll try, and If you still can't access it, tell me and I'll try a different approach – theseal53 Aug 12 '15 at 20:22
  • The reason that I use EXIT_FRAME instead of ENTER_FRAME is that I've noticed problems with children being rendered before the function is applied, making them facing the wrong way when the display list does its thing. EXIT_FRAME seems to solve this problem. – theseal53 Aug 12 '15 at 20:44

2 Answers2

2

There are couple of thing which you need to take care.

  1. You don't need to flip element based on the numChildren as it always return 1 as on each frame you will get single children.
  2. you also don't need to do the check another condition Math.abs(targetClip.scaleX) / targetClip.scaleX != -1 to set the flip.
  3. And also you need to use ENTER_FRAME instead of EXIT_FRAME. ENTER_FRAME works for the current frame whereas EXIT_FRAME works for previous frame.

Use the below code.

package 
{

    import flash.display.MovieClip;
    import flash.events.*;
    import flash.utils.setTimeout;

    public class FlipClip extends MovieClip
    {

        var mInstance
        var prevX;

        public function FlipClip()
        {
            //as soon as this is instantiated, add the eventListener
            addEventListener(Event.ENTER_FRAME,flipTheClip);
             mInstance = this;
            //mInstance.visible  = false;
        }



        public function flipTheClip(e)
        {

            this.scaleX *=  -1;
            prevX = this.x;
            if(this.scaleX < 0)
                this.x = prevX + this.width
            else
                this.x = prevX - this.width
        }

    }

}

Paste above code in FlipClip.as file and change the frame rate to 1. You need to update the moviClip placement based on your requirement.

Hope above answer solve your problem.

Randhir Kumar
  • 197
  • 10
  • The reason that I don't set the `scaleX = -1` for the parent movieclip is that I want to be able to flip certain children within the parent, while leaving others untouched. Sorry that I wasn't entirely clear about that. – theseal53 Aug 14 '15 at 19:55
1

You need to remove listener for EXIT_FRAME before playing animation. Also you are Flipping your movieClip here but not adding any code for playing it.

Paste below code in your FlipClip.as file.

package 
{

    import flash.display.MovieClip;
    import flash.events.*;
    import flash.utils.setTimeout;

    public class FlipClip extends MovieClip
    {

        var mInstance

        public function FlipClip()
        {
            //as soon as this is instantiated, add the eventListener
            addEventListener(Event.EXIT_FRAME,flipTheClip);
             mInstance = this;
            mInstance.visible  = false;
        }

        private function playallAnimation()
        {
            this.gotoAndPlay(1);
        }

        public function flipTheClip(e)
        {
            removeEventListener(Event.EXIT_FRAME,flipTheClip);

            //for sake of simplicity, we will flip every child
            for (var i=0; i<numChildren; i++)
            {

                var targetClip = getChildAt(i);
                var axis = 10;

                //if the target child has not already been flipped...
                if (Math.abs(targetClip.scaleX) / targetClip.scaleX != -1)
                {
                    //reverse the child's direction with scaleX and move based on the axis
                    targetClip.scaleX *=  -1;
                    var dist:Number = targetClip.x - axis;
                    targetClip.x = axis - dist;

                }
            }
            setTimeout(function()
            {
                mInstance.visible  = true;
                playallAnimation();
            },200);
        }

    }

}

Hope this will work for you.

Randhir Kumar
  • 197
  • 10
  • I applied this code to the FlipClip.as file, but it didn't yield the result I was hoping for. My desired outcome is that the MovieClip will play repeatedly with a flipped appearance, almost as if I had just set the MovieClip's `scaleX = -1`. But I think you might be on to something with the `setTimeout`... – theseal53 Aug 13 '15 at 15:32
  • To flip you need to add some more logic which basically scale each time. As per your code movileClip flipped first time as the scale value of x is already set to -1. In movieClip after flipping the registration point never change so If you want to update it every time you need to calculate scaleX position and x position value on each iteration. – Randhir Kumar Aug 14 '15 at 03:43
  • How would I implement this into the code? I don't entirely understand – theseal53 Aug 14 '15 at 05:04