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.
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’>