[FLASH] How to Jump to a Random Frame Label

Sources: httphttps://www.quip.net/blog/2006/flash/how-to-jump-random-frame-label
Author: David Stiller

How to Jump to a Random Frame Label



This question comes up from time to time in the forums.  Typically, someone has built a Flash banner ad with a handful of entry points.  The ad is supposed to start at any one of these, but the choice should be random.  For example, a fruit stand ad is supposed to play the bit about the bananas first, then the apples, then the bananas again, then the oranges.  How can this be accomplished?  Well, this one’s pretty easy. 



An answer, short and sweet.


Add the following to frame 1 of your scripts layer.

function getRandomLabel():String {
var labels:Array = new Array(“a”, “b”, “c”);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndStop(getRandomLabel());

Make sure to replace the “a”, “b”, and “c” with the names of actual frame labels in your movie.  (It doesn’t matter how many, but it won’t make much sense if you only put one.)


How it works


The first line declares a function that returns a string, which will provide the desired random frame label when needed.


Inside the function, we declare an array variable and assign it the value of an Array instance.  This array holds a list of our frame labels.  Next, we declare a number variable and assign it a random value based on the count of elements in the array.  The Array.length property returns this count.  The count is multiplied by Math.random(), a static method that returns a pseudo-random decimal value between zero and one.  Because the result needs to be an integer, we round the whole thing down with the Math.floor() method.  When this line is executed, index’s value will be an integer between zero and the number of items in the array.  Finally, we use the array access operator, [], to “pull” an element from the array.  In this case, labels[0] would be “a,” labels[1] would be “b,” and so on.  We’re simply randomizing the number that goes in between the square brackets.


Outside the function, a normal invocation of MovieClip.gotoAndStop() does its thing with a frame label as the parameter.  Once the custom getRandomLabel() function is declared, it can be referenced anywhere else in the timeline, so if you want to jump to a random label again after, say, frame 300, just paste that last part into a keyframe at that point.

this.gotoAndStop(getRandomLabel());

Variations


As is, the movie will immediately jump to one of your frame labels and stop – that’ll be the end of it.  If you want the playhead to jump to a frame and play, replace the reference to this.gotoAndStop() with this.gotoAndPlay(), leaving that getRandomLabel() function as a parameter, where it is.


To jump to a random frame (not frame label), the following variation will do.

function getRandomFrame():Number {
return Math.ceil(Math.random() * (this._totalframes – 1)) + 1;
}
trace(getRandomFrame());

Note the use of MovieClip._totalframes to retrieve the total number of frames in the timeline. Hardcode this number, if you like, but make sure to exclude 1 from the possible outcome. If the playhead goes to frame 1, the getRandomFrame() function is needlessly redefined.


How about visiting a series of random frame labels without repeats? For that, check out the aptly titled “How to Jump Randomly to Frame Labels without Repeats.”


FAQs

QUESTION 1:
Hi,


This was extremely helpful. I do have one question: How about if you want to pull from a random frame label at the beginning, and then play the other frames in order.


For example, let’s say it initially displays frame “three”. Then frame “four”, “five”, “one”, “two”, “three”, etc would follow.


If frame “two” was pulled initially, then “three”, “four”, “five”, “one”, etc would display.


Thanks for your help

ANSWER Q1:

Great question, Heather!


What you’re after is easy enough if we re-use that index variable. The way it’s written now, the variables index and labels are scoped to the function getRandomLabel(), which means they disappear as soon as getRandomLabel() has run its course. To scope those variables to the main timeline, so that we can re-use them for the full duration of the timeline, they need to be declared there, instead.

var labels:Array = new Array(“a”, “b”, “c”);
var index:Number = Math.floor(Math.random() * labels.length);

So at this point, we have no function: just two variables. As discussed above, the value of index at this point is either 0, 1, or 2. Let’s say it happens to be 1. We can add a third line to at least get the timeline rolling.

this.gotoAndPlay(labels[index]);

Make sense so far? We’re telling the main timeline, represented by this, to perform the MovieClip.gotoAndPlay() method, and we’re telling it to go to whatever frame is represented by labels[index] – which is to say labels[1], since index is currently 1 – which happens to be the string “b”.


In this hypothetical scenario, there are three labels, “a”, “b”, and “c”. The playhead will jump to b at this point and play until it hits another frame with ActionScript telling it to do something else. Each of your labels sits at the beginning of a span of frames – say a span of 100 frames each. On the 100th frame after “a”, “b”, or “c”, you could make that frame a keyframe and use the following ActionScript:

index++;
this.gotoAndPlay(labels[index];

In line 1, index increments to whatever it is plus 1, so in our scenario, it’s now 2. In the next line, this.gotoAndPlay() is sent to labels[2], which happens to be “c”.


So let’s follow along and see where this breaks. At frame label 3, the playhead plays through until 100 frames after that, at which point it sees the same two lines we just looked at. The value of index increments to 3, and the playhead is sent to the frame label stored in labels[3]. But wait! There are only three elements in the labels array: 0, 1, and 2. There is no 3.


Easy enough to remedy. Change those two lines to this:

index++;
if (index > labels.length) {
index = 0;
}
this.gotoAndPlay(labels[index]);

You follow? index is incremented: if it started at 0, it’s now 1; if 1, it’s now 2; if 2, it’s now 3 – and the if statement changes it back to 0. The Array.length property comes in handy, here, because we don’t even have to keep track of how many elements are in the array.


Now, we’re done to one more problem to solve. The way it is at this point, the banner will loop forever. Maybe that’s not so bad, actually. index starts at a random number and then just loops around the array until the user closes the browser or navigates elsewhere.


If you want the frame labels to only be played once, I suggest a third variable to keep track of how many times we’ve incremented index.


Here’s a recap:

// in frame 1
var labels:Array = new Array(“a”, “b”, “c”);
var index:Number = Math.floor(Math.random() * labels.length);
var counter:Number = 1;
this.gotoAndPlay(labels[[index]);

// in the last frame of each
// labeled frame span
counter++;
if (counter < labels.length) {
index++;
if (index > labels.length) {
index = 0;
}
this.gotoAndPlay(labels[index]);
} else {
stop();
}

Note that counter starts at one, because we normally start counting at one; index, on the other hand, starts at zero because arrays start at zero.

QUESTION 2:
What if I start at a main page, then with the next button, It jumps to 1 of 10 choices randomly, where would the code go?

ANSWER Q2:

All you need here is to assign the “trigger” line (the one that starts this.gotoAndPlay(…)) to the event handler of a button. Check out the original code sample … it sets up a custom function named getRandomLabel(), which you would leave as is. Then a single line uses this function, which you’ll do, too, but inside a button.


Of course, you’ll want to stop the timeline completely, so that the button causes it to start again.

function getRandomLabel():String {
var labels:Array = new Array(“a”, “b”, “c”);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.stop();
buttonInstance.onRelease = function() {
this._parent.gotoAndStop(getRandomLabel());
}

In the above sample, your button would have the instance name “buttonInstance” (or pick whatever you like; just make sure you use the actual instance name). So, first is the function declaration, followed by the MovieClip.stop() method, invoked against the main timeline.


Then, a function literal, assigned to the Button.onRelease event of your button instance. Note how the path to gotoAndStop() has changed from this to this._parent. The reason for this is because gotoAndStop() is a MovieClip method, and without the _parent, the method would be invoked against whatever this points to – which is the button, in this case (the Button class features no such method). Make sense?


‘;’ type=’text/javascript’>

Share this post! Let them know how awesome is this!
Facebook
Twitter
LinkedIn
WhatsApp
Email