Skip to main content
Participant
February 17, 2013
Answered

How do I loop back from the first frame to the last frame?

  • February 17, 2013
  • 1 reply
  • 5124 views

Hi there,

I'm currently working on the framework for a product viewer.

I have:

a movie clip called 'viewer_mc' which contains the images take from different angles of the product. The actionscript generates a script on the last frame of this that returns it to frame 1.

a button instance called 'autoplay_btn' which plays through the movie clip from whatever the current frame is, and stops on frame 1.

a left and right button which serve to move the movie clip frame, to give the appearance that the product is rotating.

I have succeeded in getting it to:

have the movie clip play through once, return to frame 1 and stop.

have the buttons return functions when held down, that move the frame in the movie clip using nextFrame and prevFrame commands. The right button successfully loops round to frame 1 and continues functioning to give the appearance of continual rotation.

The last problem I am experiencing is getting the left button to act in the corresponding manner, going from the first frame to the last and continuing to function.

Here is my actionscript so far:

import flash.events.MouseEvent;

var lastFrame:Number = viewer_mc.totalFrames;

var thisFrame:Number = viewer_mc.currentFrame;

var backFrame:Number = viewer_mc.currentFrame-1;

1. This is the part that gets it to play through once before returning to the first frame. I think perhaps the problem I am experiencing is because of the 'viewer_mc.addFrameScript(lastFrame-1, toStart)' part i.e. although I'm holding the left button, its returning to this script and therefor getting bounced back immediately to the first frame. However, there is no flicker on the screen which you might expect if this were the case

Note - as this is a generic product viewer which I can use as a template I am using lastFrame etc. as opposed to typing the value in

function toStart (){

          viewer_mc.gotoAndStop(1);

}

viewer_mc.addFrameScript(lastFrame-1, toStart);

2. This is the functionality for the autoplay_btn that will play through a rotation / return the viewer to the initial (frontal) view of the product (frame 1).

autoplay_btn.addEventListener(MouseEvent.MOUSE_DOWN, autoplay);

function autoplay (ev:MouseEvent):void{

          var startFrame:Number = viewer_mc.currentFrame;

          viewer_mc.gotoAndPlay(startFrame);

};

3. This is the functionality of the right button, which when held, moves the movie clip to the next frame via the 'rotateRight' function based on the 'nextFrame' command. It loops back round to the first frame due to the 'viewer_mc.addFrameScript(lastFrame-1, toStart)' script generated on the last frame of the movie clip, as is desired.

right_btn.addEventListener(MouseEvent.MOUSE_DOWN, rightDown);

function rightDown(e:Event){

    stage.addEventListener(MouseEvent.MOUSE_UP,stoprightDown); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.

    addEventListener(Event.ENTER_FRAME,rotateRight); //while the mouse is down, run the tick function once every frame as per the project frame rate

}

function stoprightDown(e:Event):void {

    removeEventListener(Event.ENTER_FRAME,rotateRight);  //stop running the tick function every frame now that the mouse is up

    stage.removeEventListener(MouseEvent.MOUSE_UP,stoprightDown); //remove the listener for mouse up

}

function rotateRight(e:Event):void {

    viewer_mc.nextFrame();

}

4. This is the functionality of the left button, which when held, moves the movie clip to the prev frame via the 'rotateRight' function based on the 'prevFrame' command. And this is where the problem lies, as although it works for getting the movieclip back to frame 1, it does not loop round to the last frame and continue functioning, as is wanted.

left_btn.addEventListener(MouseEvent.MOUSE_DOWN, leftDown);

function leftDown(e:Event){

    stage.addEventListener(MouseEvent.MOUSE_UP,stopleftDown); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.

    addEventListener(Event.ENTER_FRAME,rotateLeft); //while the mouse is down, run the tick function once every frame as per the project frame rate

}

function stopleftDown(e:Event):void {

    removeEventListener(Event.ENTER_FRAME,rotateLeft);  //stop running the tick function every frame now that the mouse is up

    stage.removeEventListener(MouseEvent.MOUSE_UP,stopleftDown); //remove the listener for mouse up

}

I'd imagine it is probably my logic for this part that is really letting me down - I can do a similar function in actionscript 2, but am trying to learn actionscript 3 just to move with the times as it were, and struggling a bit. Still this is only a few days in!

function rotateLeft(e:Event):void{

          if(thisFrame==1){

                    gotoAndStop(viewer_mc.totalFrames-1);

          } else{

          viewer_mc.prevFrame();

          }

}

Any help you can give me would be gratefully received. For an example of the effect I am trying to achieve with the autoplay button etc. I recommend:

http://www.fender.com/basses/precision-bass/american-standard-precision-bass

This topic has been closed for replies.
Correct answer Ned Murphy

I've put in the correction above and progress! - it now calls the prevFrame part of the function, but the gotoAndStop(viewer_mc.totalFrames-1) part, frustratingly, won't happen.

Here is what I currently have (I'm probably being stupid and missed something)

import flash.events.MouseEvent;

import flash.events.Event;

function toStart (){

          viewer_mc.gotoAndStop(1);

}

viewer_mc.addFrameScript(viewer_mc.totalFrames-1, toStart);

//last image of viewer_mc = first image of viewer_mc

autoplay_btn.addEventListener(MouseEvent.MOUSE_DOWN, autoplay);

function autoplay (ev:MouseEvent):void{

          var startFrame:Number = viewer_mc.currentFrame;

          viewer_mc.gotoAndPlay(startFrame);

};

right_btn.addEventListener(MouseEvent.MOUSE_DOWN, rightDown);

function rightDown(e:Event){

    stage.addEventListener(MouseEvent.MOUSE_UP,stoprightDown); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.

    addEventListener(Event.ENTER_FRAME,rotateRight); //while the mouse is down, run the tick function once every frame as per the project frame rate

}

function stoprightDown(e:Event):void {

    removeEventListener(Event.ENTER_FRAME,rotateRight);  //stop running the tick function every frame now that the mouse is up

    stage.removeEventListener(MouseEvent.MOUSE_UP,stoprightDown); //remove the listener for mouse up

}

function rotateRight(e:Event):void {

    viewer_mc.nextFrame();

}

left_btn.addEventListener(MouseEvent.MOUSE_DOWN, leftDown);

function leftDown(e:Event){

    stage.addEventListener(MouseEvent.MOUSE_UP,stopleftDown); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.

    addEventListener(Event.ENTER_FRAME,rotateLeft);//while the mouse is down, run the tick function once every frame as per the project frame rate

}

function stopleftDown(e:Event):void {

    removeEventListener(Event.ENTER_FRAME,rotateLeft);  //stop running the tick function every frame now that the mouse is up

    stage.removeEventListener(MouseEvent.MOUSE_UP,stopleftDown); //remove the listener for mouse up

}

function rotateLeft(e:Event):void{

                    if(viewer_mc.currentFrame==1){

                    gotoAndStop(viewer_mc.totalFrames-1);

          }else{

                    viewer_mc.prevFrame();

          }

}


Here's a link to the file I made using your code with the change I indicated for the reverse playing.  See if it works as you expect.  If so, try to see what's different in yours.  If not, tell me what it should do that it fails to.

http://www.nedwebs.com/Flash/AS3_loop_play.fla

1 reply

Ned Murphy
Legend
February 17, 2013

There's a bit too much wording to see much code in what you wrote.  For what I can see, I recommend you just use currentFrame instead of thisFrame, mainly because I can't see where you keep it updated...

function rotateLeft(e:Event):void{

          if(currentFrame==1){

                    gotoAndStop(viewer_mc.totalFrames-1);

          } else{

                    viewer_mc.prevFrame();

          }

}

One thing I am not sure of is whether you intend to go to the last frame (viewer_mc.totalFrames) or the second last frame (viewer_mc.totalFrames-1)

Participant
February 17, 2013

Thanks for getting back to me.

Here's the code without my comments / explanations:

import flash.events.MouseEvent;

import flash.events.Event;

var lastFrame:Number = viewer_mc.totalFrames;

var thisFrame:Number = viewer_mc.currentFrame;

var backFrame:Number = viewer_mc.currentFrame-1;

function toStart (){

          viewer_mc.gotoAndStop(1);

}

viewer_mc.addFrameScript(lastFrame-1, toStart);

//last image of viewer_mc = first image of viewer_mc

autoplay_btn.addEventListener(MouseEvent.MOUSE_DOWN, autoplay);

function autoplay (ev:MouseEvent):void{

          var startFrame:Number = viewer_mc.currentFrame;

          viewer_mc.gotoAndPlay(startFrame);

};

right_btn.addEventListener(MouseEvent.MOUSE_DOWN, rightDown);

function rightDown(e:Event){

    stage.addEventListener(MouseEvent.MOUSE_UP,stoprightDown); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.

    addEventListener(Event.ENTER_FRAME,rotateRight); //while the mouse is down, run the tick function once every frame as per the project frame rate

}

function stoprightDown(e:Event):void {

    removeEventListener(Event.ENTER_FRAME,rotateRight);  //stop running the tick function every frame now that the mouse is up

    stage.removeEventListener(MouseEvent.MOUSE_UP,stoprightDown); //remove the listener for mouse up

}

function rotateRight(e:Event):void {

    viewer_mc.nextFrame();

}

left_btn.addEventListener(MouseEvent.MOUSE_DOWN, leftDown);

function leftDown(e:Event){

    stage.addEventListener(MouseEvent.MOUSE_UP,stopleftDown); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.

    addEventListener(Event.ENTER_FRAME,rotateLeft);//while the mouse is down, run the tick function once every frame as per the project frame rate

}

function stopleftDown(e:Event):void {

    removeEventListener(Event.ENTER_FRAME,rotateLeft);  //stop running the tick function every frame now that the mouse is up

    stage.removeEventListener(MouseEvent.MOUSE_UP,stopleftDown); //remove the listener for mouse up

}

function rotateLeft(e:Event):void{

          viewer_mc.prevFrame();

}

The definition of the rotateLeft function is where the problem lies I think - I've taken out my poor attempts at doing the logic from the previous post. If I were to write it out long-hand the statement I want to write is: 'If you get to frame 1 and function rotateLeft is called go to the end of the movie clip'.

The reason I have to use the viewer_mc.totalFrames-1 definition in the addFrameScript call is the addFrameScript function is 0 based i.e. if you want to call frame 1 of the movieclip you have to return a value of 0 in the addFrameScript (or such is my understanding of it anyway). As such, the last image in the movie clip will need to be the view obtained at 360 degree rotation, which is of course the same view as at 0 degree rotation. As a consequence, the last frame in the movie clip is superfluous for the user, but necessary for the overall effect to be achieved. And, in addition, to keep up the effect of a 360 degree view when the rotateLeft function is called it needs to skip that last frame to go to the lastFrame-1 (or totalframes-1), or in other words, the view of the image prior to completing the full 360 rotation.

the variables thisFrame and lastFrame are defined at the very top of the script. Like you said they might need to be defined or called on again elsewhere.

Ned Murphy
Legend
February 17, 2013

Did you try the change I indicated?

When you define the values of those variables at the top, only those that do not change will retain the correct value.  The value of thisFrame (and backFrame) will be the value it was when the file started and will not automatically update as the currentFrame value changes.  That's why I say to just use the currentFrame property instead.