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.”
June 15th, 2006 at 8:29 am
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
June 15th, 2006 at 7:38 pm
Great question, Heather!
What you’re after is easy enough if we re-use that
indexvariable. The way it’s written now, the variablesindexandlabelsare scoped to the functiongetRandomLabel(), which means they disappear as soon asgetRandomLabel()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.So at this point, we have no function: just two variables. As discussed above, the value of
indexat 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.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 bylabels[index]— which is to saylabels[1], sinceindexis 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:
In line 1,
indexincrements to whatever it is plus 1, so in our scenario, it’s now 2. In the next line,this.gotoAndPlay()is sent tolabels[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
indexincrements to 3, and the playhead is sent to the frame label stored inlabels[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:
You follow?
indexis incremented: if it started at 0, it’s now 1; if 1, it’s now 2; if 2, it’s now 3 — and theifstatement changes it back to 0. TheArray.lengthproperty 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.
indexstarts 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:
Note that
counterstarts at one, because we normally start counting at one;index, on the other hand, starts at zero because arrays start at zero.July 26th, 2006 at 1:18 pm
Nice, 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?
July 26th, 2006 at 2:43 pm
willie,
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 namedgetRandomLabel(), 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.
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.onReleaseevent of your button instance. Note how the path togotoAndStop()has changed fromthistothis._parent. The reason for this is becausegotoAndStop()is aMovieClipmethod, and without the_parent, the method would be invoked against whateverthispoints to — which is the button, in this case (theButtonclass features no such method). Make sense?July 27th, 2006 at 2:54 pm
This works great!!!!. One variation that I tried to do, was take some code from the code above (in your reply to Heather) in order to only show each frame once, then go to another frame(label) that is not in the Array, but it wouldn’t work for me. Is that possible?
July 28th, 2006 at 4:54 pm
Willie,
In that case, you’d have to A) shuffle your array; B) step through the array index by index, until it has run its course; then C) send the playhead elsewhere at the end.
The Getting the Most Out of Array.sort() article suggests a few ways to shuffle your array — make sure you read NSurveyor’s comments! To step through the array, after it’s shuffled, you’ll need a variable to act as your counter. Something like this …
… will do just fine. Have your button reference the array at
counterindex first, then increment the variable.With me so far? Remember, you’re going to drop the whole custom
getRandomLabel()part, because you’re shuffling the array instead. At this point, you’re no longer pulling out a random number as your index, you’re stepping through each index in turn.You’ll have to throw in an
ifstatement to test whencounteris the same asArray.length, referencinglabels.August 9th, 2006 at 1:44 pm
Hi David. This has been really helpful in getting me started learning actionscript but I am having a hard time wrapping my head around some things.
I have a project that I need to use the same flash file (because of size) for several pages.
I need to
a. make play random
b. tell it where to start
c. tell it what frame labels to choose from
d. no repeat until the cycle is complete
This may be a bit to bite off for a beginner but I’m starting to understand bits and pieces.
If there is anyway you could help me get through this I would greatly appreciate it!
Thanks.
Michael
August 9th, 2006 at 2:02 pm
I need to add another note. I am trying to tell my actionscript where to start and what groups to play from the object param.
August 9th, 2006 at 7:47 pm
Piker,
What you’ve described sounds a lot like Willie’s question on July 28, 2006. For that question, as with yours, I recommend using an
Arrayinstance to hold the frame labels, shuffling the array, then stepping through it from beginning to end. That takes care of items A, C, and D in your list. As to B (tell it where to start), I’m not sure what you’re asking. Do you mean “tell the playhead what frame to start with”? If so,MovieClip.gotoAndStop(), as applied to the main timeline, should do it.As always, it’s a good idea to break down your big goal — in this case, a four-point list — into small goals. How comfortable are you with arrays, for example? Do you understand how to instantiate an
Arrayinstance, how to populate the array, and how to retrieve values from it? If so, great! Next, do you understand theMath.random()method (and so on …)? If not, ’s okay … just means you have to start where you’re comfortable and keep at it until it makes sense.Where, exactly, are you getting stuck?
August 10th, 2006 at 2:32 am
Frankly the whole thing is overwhelming. Just when I think I understand, it all stops working. I can usually learn pretty quickly from taking apart existing code ie; php or javascript but actionscript is really giving me a hard time. I have tried multiple forums but I always get the wrong solution or an answer to a question I didn’t ask. I really need to grab a book and start from ground zero but I have bitten off more than I can chew already and I need a hand to get it solved. I have found a randomization script that works but telling it which labels to choose from is my stumbling block. If you can please take a look at my code and modify so that I can send a variable from the url that tells the flash what group of labels to use in the randomization. Maybe the script I am working with will help someone understand:
~~~~~~~~~~~~~~~~
function getRandomLabel():String {
If (framelabel eq “set1″)
var labels:Array = new Array(”label1″,”label4″,”label6″);
If (framelabel eq “set2″)
var labels:Array = new Array(”label2″,”label3″,”label5″);
If (framelabel eq “set3″)
var labels:Array = new Array(”label3″,”label8″,”label7″);
If (framelabel eq “”)
gotoAndPlay(5);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
var counter:Number = 1;
}
this.gotoAndPlay(getRandomLabel());
~~~~~~~~~~~~~~
framelabel is the variable Im sending through the param in the html.
goal 1: tell the flash to play designated sequences via the url
Don’t laugh too hard.
Thanks,
Michael
August 10th, 2006 at 8:31 am
Piker,
Heh, if you really think you need to grab a book, then a book is probably likely to help you.
That surprises me, actually. ActionScript and JavaScript are both based on the ECMAScript standard … they’re very similar, so if you can pick apart JavaScript, you already have a leg up.
Based on your code, you’re fairly close. You’re asking for help along very similar lines to what Willie asked for. Your series of
ifstatements is a reasonable way to provide a variety of label choices. (Note, you could declare thelablesarray once, before theifstatements, then useArray.push()to add your labels within eachifstatement, but what you have is fine.)The
eqoperator has been deprecated for a long time. Replace that with the equality operator,==. I assume you intend to use thecountervariable at a later time, but two things will keep that from happening: first, you’re declaring it after the function’sreturnstatement. Once areturnis executed, the function is done, period; second: you’re declaring it in the scope of this function, which means the variable is only visible to this function. Declare it outside the function if you want to use it later.You found it right in this article!
If you hardcode that
framelabelvariable, does your code work as expected? If it does, you’re ready to handle the next part of your goal, which is to load a variable from outside the SWF.There are a number of ways to do this. You can append a query to the SWF reference in your HTML, in the
<object>element’s<param>element and the<embed>element. You can use FlashVars, which amounts to practically the same thing. Or, from inside the SWF itself, you can useloadVariables(),loadVariablesNum(), or theLoadVarsclass.August 10th, 2006 at 1:04 pm
Thanks so much for the help. It looks like the script is working but it is only using the second to last If statement. The “set3″ statement.
My html looks like this:
I updated the AS:
function getRandomLabel():String {
If (framelabel == “set1″)
var labels:Array = new Array(”label1″,”label4″,”label6″);
If (framelabel == “set2″)
var labels:Array = new Array(”label2″,”label3″,”label5″);
If (framelabel == “set3″)
var labels:Array = new Array(”label3″,”label8″,”label7″);
If (framelabel == “”)
gotoAndPlay(5);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndPlay(getRandomLabel());
August 10th, 2006 at 1:44 pm
Piker,
I’m afraid your HTML didn’t come through.
That’s no surprise, though … I’m sure the WordPress comment system stripped that out. If your HTML follows the guidelines in the URL I suggested, you should be fine.
Now what you need are some troubleshooting techniques.
I wrote an AS2 troubleshooting article for the Adobe Developer Center not long ago. That gives you a crash course on how to “see what’s going on” in your SWFs, even if they’re hosted in a browser.
August 10th, 2006 at 2:10 pm
Maybe this will make it…
Checking out the troubleshooting now.
object
param name=”FlashVars” value=”framelabel=set2″ />
param name=”movie” value=”testd.swf?framelabel=set2″” />
param name=”quality” value=”high” />
param name=”bgcolor” value=”#ffffff” />
embed src=”testd.swf?framelabel=set2″ quality=”high” bgcolor=”#ffffff” width=”760″ height=”238″ name=”urlvariables” align=”middle” type=”application/x-shockwave-flash” pluginspage=”http://www.macromedia.com/go/getflashplayer” />
param name=”FlashVars” value=”framelabel=set2″” />
object
August 10th, 2006 at 2:17 pm
In that HTML, you’re using both techniques. As far as I know, you only need one (either FlashVars or the query string). I think you’ll get a kick out of troubleshooting tools like
trace()and the Debugger panel, because they let you actually see the value of variables as the SWF runs — tremendously helpful.August 10th, 2006 at 3:44 pm
I am an idiot…
lowercase IF.
sigh.
Thanks again for all the help!
October 6th, 2006 at 11:05 am
[…] Scheinbar funktioniert der Aufruf gotoAndStop(ziel) nicht (immer), wenn ziel eine String-Variable ist, die die Bezeichnung des Zielframes enthält. Ein Workaround könnte sein, this.gotoAndStop(ziel) zu verwenden. Darauf gebracht hat mich dieser Artikel: How to Jump to a Random Frame Label […]
October 11th, 2006 at 3:00 am
Incredibly helpful…
Thank you very much!
October 15th, 2006 at 6:28 pm
d3v1an7,
Rock on. Glad to help.
October 26th, 2006 at 10:21 am
I’m attempting to use the “Short and Sweet” framelabel version to load a random label from 13 available labels in one timeline, with “this.gotoAndPlay(getRandomLabel());”.
Right now I have a preloader scene, and in theory, the preloader would check that a certain number of required bytes would load before the second scene would be loaded. Frame 1 of Scene 2 (with the 13 labels) would hopefully load a random one. So far I just keep getting the first label on every load.
Ideally I’d actually like to put the random load script on frame three of the preloader, so that when Scene 2 loops back to frame 1, it doesn’t randomize it every time (I have tweens between the labels and I don’t want any ‘blips’).
Any idea what I might be doing wrong?
October 28th, 2006 at 11:30 am
I have a problem! I did everything that I was souposed to do but It only jumps on the first and the second label,
heres my script
function getRandomLabel():String {
var labels:Array = new Array(”advert1″, “advert2″, “advert3″, “advert4″, “advert5″);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndStop(getRandomLabel());
October 28th, 2006 at 11:41 pm
Becky,
You mentioned Scenes, so I wonder if you’re running into the problem described in “Why Doesn’t _root.gotoAndPlay() Work with Scenes?” Also, you mention “Frame 1 of Scene 2 (with the 13 labels)” (emphasis mine). Do you have more than one frame label on a given frame? That might be it. I can’t quite tell from your description if your problem may be related to the preloader. Write back if you still have questions.
October 28th, 2006 at 11:46 pm
Kevin,
Do all five labels exist somewhere on your timeline? If so, I recommend you troubleshoot by using the
trace()function. Add the linetrace(labels[index]);immediately before thereturnline — this will indicate to you which labels are being chosen from your array, so you can actually “see” them rather than only see the result of thegotoAndStop().November 2nd, 2006 at 1:23 pm
David,
I seem to be having the same problem as Kevin. I have used the recommended trace function to see which label it should be jumping to.
I have inserted the following code
function getRandomLabel():String {
var labels:Array = new Array(”pointA”, “pointB”, “pointC”, “pointD”, “pointE”, “pointF”);
var index:Number = Math.floor(Math.random() * labels.length);
trace ( index )
return labels[index];
}
this.gotoAndPlay(getRandomLabel());
At first I created a bare bones test file to make sure the script would work. But as I inserted all my frames and labels it’s not working anymore. For some reason when it tries to jump to the 4rth or 5rth label in the array it just defaults back to the 1st label.
Oh and also. When I test it out of flash it semi works. But then why I try to test out of flash player or firefox it starts at the first frame all the time. BUT it works in safari? What the is going on?
Why is this happening?
Thanks for all your help!
November 2nd, 2006 at 5:15 pm
Hello,
I think I found out the problem. It seems that if the file size is larger and has many frames then when you first load the swf movie if the frame you are trying to jump is not loaded yet then it will default to the 1st frame (or second in my case). For example if you are trying to jump to a point in frame 700 and that frame is not loaded yet then it will just play the next frame.
Kevin. Try adding a preloader to your flash file and then test it.
November 3rd, 2006 at 1:58 pm
Eddie,
You nailed it! There might be other issues affecting this, but the one you mentioned is almost certainly the culprit. If a given frame hasn’t loaded, it can’t (yet) be visited — which only makes sense. Good sleuthing!
November 23rd, 2006 at 6:01 am
Hello,
Is there away in flash to reference the passed in FlashVars or url.string vars dynamically instead of by paired name ie FlashVar.length or var textField1.text = flashVars[0]; - I hope you know what I mean here … as the string passed in could be 1 value or many … I want to loop thru the variables and creat text fields dynamically to accommodate but won’t know the names of the variables
Thanks in advance as I have been looking for information for days now
Markus
November 27th, 2006 at 3:09 am
Markus,
See my reply to your question in the comments section of this article.
January 6th, 2007 at 2:10 pm
I’ve run through about 15-20 different full pieces of actionscript code to try to get a gotoRandomLabel code that actually worked. You have really helped me out, and I really appreciate it.
Using frame labels to work in different scenes has really removed the clutter from my work.
This random label jump is perfect for my Animation Podcast thing I’m doing.
Thanks again,
-Bobby
January 6th, 2007 at 5:36 pm
Glad to hear it, Bobby!
February 7th, 2007 at 7:56 pm
I wrote the following code and got an error. It is your code so it should work. The only thing I changed was the name of the frames…:
function getRandomLabel():String {
var labels:Array = new Array(”quote_01″, “quote_02″, “quote_03″,”quote_04″, “quote_05″, “quote_06″, “quote_07″);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
};
but then I get this error in the output box:
**Error** Scene=Scene 2, layer=actions, frame=1:Line 12: ‘{’ expected
function getRandomLabel():String {
**Error** Scene=Scene 2, layer=actions, frame=1:Line 16: Unexpected ‘}’ encountered
};
what have i done wrong?
Thanks.
Van
February 8th, 2007 at 8:11 pm
Van,
While Flash’s compiler errors are usually helpful, there are times when the line numbers mentioned are a bit “off,” depending on exactly that’s wrong. Your code looks good to me — but I do notice, for example, that errors have occurred on lines 12 and 16, even though your sample is only four lines long. That tells me there’s more code involved, but you haven’t shown it.
February 10th, 2007 at 4:50 pm
David - great stuff.
Here is my situation. I have 12 labels on my timeline. I’m using your code to randomly move from label to label. Everything is working and doing exactly what you have described. Now here the variation that I’m trying to incorporate. I would like to eliminate repetition of the 12 labels. So if label 5 is the first label that the playhead jumps to, then it would not jump back to label 5 till all other labels were played. Once all 12 labels were played the loop would begin again.
Thank you for your help. Brian
February 10th, 2007 at 8:46 pm
Brian,
I see two different ways to handle this.
For the first variation, you’ll need to remove the array from the
getRandomLabel()function, because as it currently stands, that function re-creates the array every times it’s called. Frankly, what I’ve shown isn’t especially optimized, and I probably should have created the array outside the function in the first place, but I try to balance brevity/simplicity in these articles against Razzle Dazzle Fully Optimized Spotless Code. Sometimes I break from absolute best practices to illustrate a point.Consider the following:
What has changed? Here, the first line remains the same. The second line introduces a new variable,
You can use the
output, to temporarily store the retrieved element’s string, rather thanreturning it, as was done before. Next, theArray.splice()method is used to delete that element from the array. Finally, theoutputvariable is returned. How doesArray.splice()work? It can actually be used to add things to an array, rather than merely delete — but in this case, theindexvariable is used to specify a particular location in the array, and the second parameter, 1, says, “Okay, starting from pointindex, remove one element.” So there you have it.Array.lengthproperty to keep track of how many elements are in your array … when the number hits zero, you’ll know it’s time to set the array back to the original series (here, “a”, “b”, “c”, “d”, and “e”) and start again.For the second approach, you don’t need any of the existing “random picker” code at all. Instead, check out this Array article (and read the comments, as well!) to find the shuffle code that best suits you. Once you shuffle your array, simply step through it in order. Use, say, a
currentvariable and increment it (++) each time ask for the next array element. After your array is shuffled, your replacement for thegetRandomLabel()function might be something like this …… keeping in mind, of course, then you’ll have to start over when the value of
currentequals theArray.lengthvalue for thelabelsarray.February 20th, 2007 at 1:20 pm
David, i have a project in which i must make a quiz… one of the requirements is that the questions come up randomly and do not repeat. I am trying to do this by putting each of the 15 questions in its own scene then using an array to call the scenes randomly. the problem i am having is stopping them repeating. Any help would be fantastic mate!
thanks for your time,
Craig
February 20th, 2007 at 1:25 pm
Craig,
See my reply to Brian (immediately before your comment) for an approach to what you need. I should probably write a blog article devoted specifically to this request, because I hear it fairly often — in fact, it’s on my list — but in the mean time, put your frame labels into an array and “shuffle” the array, then simply step through the array from start to finish. If you’re using Scenes, I strongly recommend you forego Scene names in favor of frame labels.
February 21st, 2007 at 10:47 am
thanks david im almost there, i have tested the code and i can get the scenes to play randomly by putting labels at the beginning of each scene (Q1, Q2, Q3….. throught to Q15) which are all the questions. I have this code in the first frame of scene 1:
function getRandomLabel():String {
var labels:Array = new Array(”Q1″, “Q2″, “Q3″, “Q4″, “Q5″, “Q6″, “Q7″, “Q8″, “Q9″, “Q10″, “Q11″, “Q12″, “Q13″, “Q14″, “Q15″);
var index:Number = Math.floor(Math.random() * labels.length);
var output:String = labels[index];
labels.splice(index, 1);
return output;
}
and in the buttons at the end of each scene i have the code:
on (release) {
this.gotoAndPlay(getRandomLabel());
}
it seems to play scenes at random but it still repeats scenes, this is the last part of this project i need to get working and its been torturing me for weeks! Hope you can help. You mention scene names, how would i use them in this code?
Thank you so much for your help so far mate.
Craig
February 21st, 2007 at 2:04 pm
Craig,
You’re close! Note that you’re re-creating that
labelsarray every time you call thegetRandomLabel()function. Move the array declaration outside your function: that creates one. and only one,Arrayinstance, which yourArray.splice()method will “eat away” over the course of repeatedgetRandomLabel()function calls.February 22nd, 2007 at 11:19 am
Just a note to say thank you very much David! You have totally solved this problem for me and i am so grateful… I can’t believe you don’t charge for this because its such a good service you are providing! you are saved in my favourites so expect to hear from me again
Thanks again mate, Craig
February 22nd, 2007 at 11:32 am
Craig,
Glad to help, bro.
Actually, I do charge for this sort of consultation, but in an arena like this (blogs, forums) I feel strongly that free public service is a good thing, and I love to share in people’s moments of “aha!”
March 15th, 2007 at 9:09 am
David,
I am having a problem with the coding. Here is my code.
function getRandomLabel():String {
var labels:Array = new Array(”1″, “2″, “3″ , “4″);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndPlay());
***** This is the error*****
**Error** Scene=Scene 1, layer=Layer 19, frame=1:Line 1: ‘{’ expected
function getRandomLabel():String {
**Error** Scene=Scene 1, layer=Layer 19, frame=1:Line 5: Unexpected ‘}’ encountered
}
Total ActionScript Errors: 2 Reported Errors: 2
PLEASE HELP! - THANKS!
March 15th, 2007 at 9:16 am
Justin,
I don’t get the same error when I copy/paste that code (I see a different one), but depending on your version of Flash, the compiler might complain in different ways. You need to think of brackets, braces, and parentheses in terms of … well, sandwiches. Every slice of bread must have its partner. If you start a “sandwich” with
{, such as the beginning of thatgetRandomLabelfunction, sooner or later there needs to be a}… which there is. Later, in the last line, you’ve gotthis.gotoAndPlay());— with two closing parentheses ())). That’s a broken sandwich. Get rid of one of the doubled-up close parentheses.March 15th, 2007 at 9:28 am
Thanks for your help!
I also like the way you explain things (sandwich) rather than just telling someone what to do. That really helps for future problems!
I am still getting the same error. I am using version 8. I also did a publish preview and confirmed that it is not working. Maybe I did my labels wrong -that is pretty simple though.
March 15th, 2007 at 9:42 am
Justin,
This sounds like a perfect opportunity to try some troubleshooting.
Start with an empty function declaration …
… and test that. You’ll get an error, stating that a
returnstatement is required, but that’s because the function ends in:String, which means this function is supposed to return a string. So at least that error makes sense.Next, make the error go away by returning a string. For now, it can be just an empty string.
All we care about is getting rid of the error.
Next, add one line.
Test that, see if you get an error. Keep going in this way, and build up your function until you get an error you can’t account for. Don’t forget to change the
returnstatement back to what it’s really supposed to be, by the time you’re done.Couple thoughts, while you’re at it. Your array contains numbers ( … they’re quoted, so they’re actually strings). Do you mean to do that? If these are frame labels, you probably want labels in there. If you want numbers, that’s fine, but then you don’t need to quote them. If you don’t quote them, then your function will be returning a number, so you’ll want to change
:Stringat the beginning of the function to:Number. Make sense?March 15th, 2007 at 10:01 am
Sorry to keep bothering you, but I get that error right off the bat. When i put in -
function getRandomLabel():String {
}
I get the same error -
**Error** Scene=Scene 1, layer=Layer 15, frame=1:Line 1: ‘{’ expected
function getRandomLabel():String {
**Error** Scene=Scene 1, layer=Layer 15, frame=1:Line 2: Unexpected ‘}’ encountered
}
Total ActionScript Errors: 2 Reported Errors: 2
March 15th, 2007 at 10:29 am
Justin,
Are your Publish Settings set for ActionScript 2.0?
If not, either set them for ActionScript 2.0 or leave as is, but drop the post colon suffixes in your code:
April 1st, 2007 at 9:46 pm
Forgive a probably layman question, but when I publish the finished Flash, I get:
Scene=Scene 1, Layer=scripts, Frame=1: Line 1: ‘{’ expected
function getRandomLabel():String {
Scene=Scene 1, Layer=scripts, Frame=1: Line 5: Unexpected ‘}’ encountered
}
…and the player doesn’t load the frames randomly…what might I be missing or doing wrong.
Thank you
April 1st, 2007 at 10:04 pm
Jake25,
I’ll bet you’re publishing for ActionScript 1.0, which doesn’t like post colon suffixes, such as
:String. Either publish for ActionScript 2.0, or drop the strong typing. Let me know if that solves it for you.April 1st, 2007 at 10:24 pm
Please disregard my previous question…error message…
However, I am missing something else;
I have a movie that plays a timeline with nine layers. At equal points on the timeline I have named keyframes (smith, jones, etc.). I have this code in a blank keyframe on a scripts layer (it was pasted into the advanced window of the actions pallet for this frame):
function getRandomLabel() {
var labels = new Array(”banos”, “barone”, “benoun”, “conway”, “fox”, “irzakhanian”, “potier”, “rottler”, “skipworth”, “werkmeister”, “wilson”);
var index = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndPlay();
The movie is set to play through from beginning to end without any action frames other than frame #1 listed above.
The movie plays from beginning to end, but will not go to the named keyframes randomly…it just plays in order all the time.
Is there something else I should be doing…fyi, this is my first attempt at action scripting.
April 2nd, 2007 at 12:22 am
I have another solution for my issue, but have one question regarding it as well…
My question is at the bottom.
—
Name each keyframe:
a1, a2, etc. to a11
Place in the first frame:
function chooser(){
ran=random(11);
gotoAndPlay(”a”+ran);
}
— (11) being the number of labeled keyframes —
Place in the last frame of each animated section:
_root.chooser ();
——-
How can I make this script not repeat a frame/s until each of the 11 have been displayed?
April 2nd, 2007 at 12:27 am
Yes, I noticed that after I posted…thanks for the reply…
—
I’ll bet you’re publishing for ActionScript 1.0, which doesn’t like post colon suffixes, such as :String. Either publish for ActionScript 2.0, or drop the strong typing. Let me know if that solves it for you.
April 2nd, 2007 at 8:30 am
Jake25,
This is in reply to your last three posts.
In the April 1, 10:24pm reply, you posted some code and wondered why your movie played through without ever visiting the labels.
The reason for this is that you aren’t using the custom
getRandomLabel()function you wrote. In the line immediately following your function, you’ve got this:The
MovieClip.gotoAndPlay()method requires a parameter, and you haven’t provided one. Inside those parentheses, you need to make a function call togetRandomLabel(), which returns the label you’re after:In your other approach …
… you’re taking practically the same approach. In this code, as in mine, a new random number is chosen every time, which means repeats are likely to occur.
Check back in my previous reply to Brian (Feb 10) to see a few rough suggestions. This question has come up often enough that it makes sense to respond to it in a dedicated blog entry, so I’ve added that to my list.
April 25th, 2007 at 3:35 pm
Hi there,
For some reason, I have some troubles with the code (especially w/ my very limited flash knowledge). I’m wondering if you can help me figure this out. I put the code on the first frame (there’s nothing on the 1st frame except the code):
function getRandomLabel():String {
var labels:Array = new Array(”a”, “b”, “c”);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndPlay(getRandomLabel());
But for whatever reason, it ignores the code, and just plays the whole frames (from 2nd frame to end). I tried to put stop(); but it just make it stop and does nothing. what should I do?
Thanks
April 25th, 2007 at 11:50 pm
ska,
Do you have three frame labels by the name of “a”, “b”, and “c” in your movie?
April 26th, 2007 at 10:23 am
yes, I do, exactly the same name, but it still doesn’t do anything..
I am really frustrated…
Is it possible that this is because of how the file set up on certain way or something?
April 26th, 2007 at 3:01 pm
It works! I’m not really sure how, but we put the actionscript not on the 1st frame (frame 5 for ex.) and it goes well.
Thanks anyway… your site is very useful.
April 27th, 2007 at 9:05 am
ska,
Glad to hear it! I’m baffled by your solution … there must be something else going on to affect the success of the script on frame 1. But hey, you got it working! Good for you!
May 7th, 2007 at 1:03 pm
David,
I’ve been using the following script (which works fine) to jump to a random label in my movie:
// define a array with all your previously defined labels
labelarray=[”3M”, “Dentsply”, “Imagen”, “KaVo”, “CMC”, “Atlantis”, “Sirona”, “Etkon”, “Geomagic”, “Ivoclar”, “IMC”, “CMC2″, “NB”, “Wieland”, “Atlantis”, “Delcam”];
// calculate a random index for this array
randomidx = random(labelarray.length);
// jump to the label at the random index
gotoAndPlay(labelarray[randomidx]);
But what I really want is a true “shuffle” of the entire label array so that all of the labels are jumped to and played once in a random order and then shuffled again. Is this possible using my existing script or a variation of yours?
May 8th, 2007 at 9:46 pm
Tomas,
It sure is. In that case, you’d forget the whole random choice part and simply step through the array from start to finish — after it’s been shuffled, of course. You could set a
currentLabelvariable and, at the end of each span of frames, put something like …Sooner or later, I’ll blog specifically about a shuffle routines, but in the mean time, use Google to search for “kglad shuffle” and/or “Rothrock shuffle”; these are regulars on the Adobe forums, and both of their names are associated with the same particular approach. You’ll find a somewhat older
Object.prototypeversion, but if you keep looking, you’ll find AS2 transcriptions. There’s also a brief mention of shuffling on this blog in “Getting the Most Out of Array.sort().”May 15th, 2007 at 1:29 pm
Hi there,
Does anyone know why I’m getting this?
**Error** Symbol=xingfruit, layer=Layer 3, frame=5:Line 2: Expected a field name after ‘.’ operator.
var labels:Array = new Array(”a”, “b”, “c”, “d”. “e”, “f”, “g”, “h”, “i”);
**Error** Symbol=xingfruit, layer=Layer 3, frame=5:Line 5: Unexpected ‘}’ encountered
}
**Error** Symbol=xingfruit, layer=Layer 3, frame=5:Line 1: A return statement is required in this function.
function getRandomLabel():String {
Total ActionScript Errors: 3 Reported Errors: 3
__________
I have a movie clip with the code on the first frame and have labelled frames
a b c d e f g h i at 10 frames apart and just want it to randomly jump
Any help appreciatd
:0)
May 15th, 2007 at 1:39 pm
anthony,
Are you publishing to ActionScript 2.0? Do you have a
returnstatement in yourgetRandomLabel()function?May 17th, 2007 at 9:47 am
David,
Thanks for your help. Unfortunatly, I’m really only a Flash designer that uses AS only when I have to and can find something that works. I didn’t write the orginal script and I don’t quite understand how to shuffle the initial array so that I can then use the code you provided (which I think I understand) to step through it. Also, I assume I could change the stop command to jump back to the shuffle script to start the whole thing over again once it’s done, right? Any help would be much appreciated.
May 30th, 2007 at 8:32 am
Thomas,
There are a number of popular shuffle algorithms on the Web, but I know they can seem forbidding if you’re not already a programmer. To answer your need, I’ve posted a new article that uses one of the most popular shuffle functions I know.
July 18th, 2007 at 10:36 am
In regards to a comment made by ska in april, I wasn’t able to get my movie working, but by moving the actionscript code to frame #2 fixed the problem.
Thanks for the tutorial, I never would have figured out how to do it on my own.
July 25th, 2007 at 12:17 pm
ct,
Thanks!
September 6th, 2007 at 5:28 am
Hi David,
I’m having a bit of a problem (seems like a bug), with this code. Everything works fine when i have random text at various points on my timeline. My problem occurs when i introduce images to the timeline, more specifically 3 images.
I have placed letter characters a,b,c, etc inline with a,b,c, etc labels, the script is on the first frame and runs fine. When i add an image to a seperate layer inline with a label i.e. ‘a’ the script still works fine and randomly jumps. If i add a further two images (to make three) to the timeline at various points the code suddenly decides to load at ‘a’ almost always, and occasionaly ‘b’ or’c’ buts that it. My movie contains labels from ‘a’ to ‘i’ (as does my Array).
Any ideas (i’m running flash 8 pro).
Thanks Simon
November 20th, 2007 at 9:36 pm
[Follow up on Simon …]
Simon eventually figured out what was going on. From an email: “the problem centered around using Actionscript 2 on one machine and 3 on another.” Glad you solved it!
January 4th, 2008 at 1:11 pm
I am wondering how to make this swap each time the movie clip loops, instead of each time the page is loaded? Thanks for your help!
January 7th, 2008 at 9:32 am
abbi,
As long as the movie loops back to frame 1, where the above code is located, it should act as if it had reloaded, which would give you what you’re looking for. You might also check out “How to Jump Randomly to Frame Labels without Repeats.”
January 22nd, 2008 at 3:55 pm
I am creating a splash page and want to play frames randomly which I have done however, I don’t want the same frame to to play FIRST AGAIN if you have visited my site already that day. How do I do this? The splash page is not up yet - let me know if you want me to upload. Thanks!!! Shay
January 22nd, 2008 at 4:53 pm
Shay,
In order for Flash Player to “remember” anything from day to day — might be the user’s name, a high score, or which frame(s) to visit from a random selection — you’ll need to use the
SharedObjectclass, which is essentially the Flash version of browser cookies.I wrote an AS2 article on this topic, “How to Store Persistent Data with the SharedObject Class,” that should help you get started. I could see using
SharedObjectto store an abbreviated version of thelabelsarray, dropping off the any frame labels that have already been used. You’ll also want to check theDateclass to find out what time/date it is when the users visits.For this particular question, I haven’t have a spelled-out answer off the top of my head. I keep a huge TO DO list for blog articles, and I’ve added your question to it.
Every one of these entries really does get an answer … eventually … but it always comes down to spare time, so it’s a bit like playing roulette.
March 6th, 2008 at 6:09 pm
Hey Dave,
Thanks much for this post. I have a question on it. I used the simple code at the top but it’s not working for me. I think that perhaps it’s because the labels that I’m referencing are in different scenes. Is it possible that this code would not work because of that? Is there such thing as getrandomScene? Basically I have a bunch of scenes that I want to play at random.
Thanks,
Bill
March 6th, 2008 at 8:51 pm
Bill,
You shouldn’t have any trouble with scenes, as long as your code references the label name only — not the scene and the label — and provided your labels are unique across all scenes.
March 31st, 2008 at 10:34 pm
Hi dave,
the code didnt really work for me. is it because i added buttons/images? i have different images on different frames and i want to display different images at random, but somehow it doesnt work.
April 1st, 2008 at 9:42 am
Joyce,
Buttons and images shouldn’t harm a thing, though you didn’t mention how you used those in conjunction with the sample code. Is your FLA document configured for ActionScript 2.0? Often, it helps to start small and build your way toward a goal. Start a FLA file without buttons and images — just use shapes on, say, three different frame — and use that as a proof of concept. When that works (it should!) replace the shapes with images. When that works, increase the images from three to eight, etc. Then add your buttons.
April 10th, 2008 at 1:12 pm
David,
I’ve applied this code and it works wonderfully with a single scene. However, when I try to apply it to one scene in an environment with many of them, it doesn’t seem to work quite right. I only have labels on the last scene, but when it runs the gotoNextLabel it returns to the first frame of the first scene. For some reason it seems to ignore the actual frame labels.
This scene on its own works perfectly. When it’s part of a movie with other scenes it acts a little strange. Am I missing something?
April 10th, 2008 at 2:06 pm
Adam,
I wonder if you’re running into the issue described in “Why Doesn’t _root.gotoAndPlay() Work with Scenes“?
April 10th, 2008 at 2:36 pm
Perfect! A little extra reading would have done me well, I guess.
I changed the line to read:
this.gotoAndPlay(labels[currentLabel]);
Thank you for your help!
April 10th, 2008 at 2:40 pm
Adam,
There you go! Cool!
July 2nd, 2008 at 8:32 am
Hi David!!… first off all congratulations for this amazing and helpfull blog you have!!… i’m a young designer trying to learn some cool stuff in flash… i was trying to make a random slideshow in a website whit this actionscript codes you’ve provided in this post…
but the thing is, the random slideshow is workin’ fine, i click to go to the frame where the random slideshow mc is and it works just fine, but when i click to go back to “homepage” (for example) the whole thing turns a mess… jumping from one frame to another…….
it’s just like if the random mc code was still workin outside the mc!!!
Could you give me some help??
best regards, Danny
August 10th, 2008 at 10:50 am
Thanks for the script. I tried this out and it worked great (using gotoAndPlay in the last line) and got all excited, but then when I finished my very long animation, it only works to a point. First off, I’m totally new to AS and don’t know how to label a frame, but it seems that if you just use the frame number, it works just as well. Only, it quits working if the frame number is too high. For instance, this works fine:
function getRandomLabel():String {
var labels:Array = new Array(”6″, “66″, “126″, “186″);
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndPlay(getRandomLabel());
but if I add a frame number higher than 231, it just goes to frame 231 every time and won’t go any higher. It may still go to 6, 66, 126, or 186, but won’t go higher than 231. Is this because I really need to actually label the frames? If so, how do I?
Thanks in advance.
August 10th, 2008 at 9:39 pm
To danny …
Apologies for the late reply!
Off the top of my head, I’m afraid I’m not sure what might be causing this — actually, not sure I can even envision it. The only thing that should be telling the movie clip to jump anywhere are your series of
gotoAndPlay()calls, and if you’re preceding that with thethiskeyword (and assuming those statements are inside the keyframes of the movie clip in question), then only that movie clip should be jumping around.But maybe that’s just it? Is that movie clip continuing to play, even when you send the main timeline elsewhere? If so, you can give that movie clip an instance name and invoke
MovieClip.stop()on it … or hide it by setting itsMovieClip._visibleproperty tofalse. Do any of these suggestions make sense? I might be missing the mark completely, so let me know if I can re-phrase to try to suggest a few other avenues.To Gary …
You’ll be pleased to hear it’s super easy.
I generally create a Timeline layer just for labels, same as for ActionScript. Add a keyframe to whatever frame you want labeled, then click that frame to select it. Look at the Property inspector, and you’ll see right where you can specify your label.
Yes. The
MovieClip.gotoAndPlay()method accepts either a number (for frames) or a string (for labels).It shouldn’t matter, but the fact that it keeps getting stuck on 231 for you makes me wonder if your timeline has more than 231 frames. If it doesn’t, then 231 is the end of the line. If you choose to use frame numbers rather than labels, you should rewrite the
getRandomLabel()function like this:… not that it makes any difference what the function is called, but at least this way you’re actually returning numbers, rather than strings (notice the
:Numberdatatype on the function’s return value, and the omitted quotation marks on the array’s items).You should be able to put any numbers in there you please, as long as the timeline that contains this code has that many frames. If you have especially heavy assets in that particular timeline, it might be that Flash Player is still loading those frames, while
gotoAndPlay()makes the attempt to jump to a frame that doesn’t exist … yet.Might that be it?
August 12th, 2008 at 12:02 am
I changed the code as you suggested. It’s still doing the same thing, but in a measure of troubleshooting, I allowed the last frame to loop back to frame one so that the entire file would be loaded. When refreshing the web page with the flash file, it still won’t start on any frame higher than 231, but when it loops back, it works just fine. Therefore, I guess it’s just not loading fast enough for my images. It’s a rather extensive slideshow with lots of pictures, animated text and logos. I guess it’s back to the drawing board for this one.
Thanks for your help. BTW, I like the new code better. It just feels right.
Thanks,
Gary
August 12th, 2008 at 8:24 am
Gary,
If you’re testing from within Flash, the loading aspect shouldn’t be an issue, so I’m still a bit puzzled. Still, I’m glad that you feel more comfortable about the numeric version.
For sake of troubleshooting, I suggest you copy/paste this same (or similar) code into a brand new FLA with very little content — perhaps a few simple shapes — and see if you run into the same limitation (you shouldn’t). That may help you pinpoint what’s going on in your actual content FLA.
January 31st, 2009 at 6:24 am
hi david, i just wanted to thank you very much for this helpful post.
May 26th, 2009 at 10:09 pm
Hi David
I’ve got a project that requires much the same as Heather Adams from June 15th, 2006, further up this post. I’m having some trouble with it, so wondering if you can help please. Action Script 2 preferred.
I’ve got a 205 frame anim with 16 frame labels, and I need the animation to run from a random starting label, then just play normally, and when at end frame loop back to start (or frame 2 so that it doesn’t trigger random label action).
I’ve tried the following from post above:
var labels:Array = new Array(”Frame1″, “Frame2″, “Frame3″, “Frame4″, “Frame5″, “Frame6″, “Frame7″, “Frame8″, “Frame9″, “Frame10″, “Frame11″, “Frame12″, “Frame13″, “Frame14″, “Frame15″, “Frame16″);
var index:Number = Math.floor(Math.random() * labels.length);
this.gotoAndPlay(labels[index]);
but it doesn’t seam to work. On testing 23 times, the first 19 started on frame 1, then label 3, then frame 1, then label 2. Not very random. My action script is on frame 1, and was copy pasted from this post. I’m running CS3 ?? Any thoughts? I’d be very grateful for your assistance.
Cheers
Kristi
May 26th, 2009 at 10:13 pm
Hi David
Please ignore my previous question, in going back through the post above (it’s very long), I’ve found a comment about putting code on frame 2 instead of 1, and this works! yeehaa, thank you.
Cheers
Kristi
June 25th, 2009 at 4:50 pm
im making a brick break game and i want to spice it up a bit. i want it so when the ball hits a brick, it will go to a random frame in that ball mc.
onClipEvent(enterFrame) {
if ((this.hitTest(_root.ball))) {
_root.ball.yspeed = -_root.ball.yspeed;
_root.ball.gotoAndStop(2);
this.play();
}
}
on frame two is a red ball, when i try to make it go to a random frame, it doesnt work, however, i got it to go to the second ball frame
help! if you need it explained bettter please ask
August 17th, 2009 at 3:53 am
Just the ticket!! - thanks very much.
August 25th, 2009 at 9:04 pm
Hi David,
Great Articles, i have a question on arrays of frame numbers. Can i put an array of frame numbers, that are from one movie timeline on the stage, that triggers another movie to play (which only goes to the next label) each time it reaches one of the frame numbers in the array.
Thanks
August 26th, 2009 at 8:30 am
To Darkroom …
You’re welcome!
To Kristi …
Hey, glad you found a solution! Good deal!
To david …
Sorry for the delayed reply! I think I understand what you’re asking. Assuming your code does work, as shown, then the randomized part is the only thing that needs to change — and it’ll replace the number 2 inside your
gotoAndStop().First, here’s what you had:
I suspect you don’t really need the
_rootreferences in there, but because I don’t have your file to test with, I’m going to go ahead and keep using it. For the randomized part, you’ll want to check how many frames are insideball(that’s theMovieClip._totalframesproperty), then use that number to generate a random number within the correct range.See the difference? Let me know if that works for you (and here’s hoping this answer isn’t too late to help you).
To Lenny …
Glad to help!
To Will …
I’m not exactly sure I understand your question, I’m afraid. I think the answer is yes, but I should clarify a few things. First, if you’re sending the playhead to a frame number, you don’t need an array. You can just use plain numbers, as I showed in my reply to david (just prior to my reply to Lenny in this block of replies).
When you say “triggers another movie,” my hunch is that you mean another movie clip, and if that’s so, then all you need to do is reference that movie clip’s instance name to access how many frames it has. In that same sentence, though, you said “which only goes to the next label,” so you might need an array after all (simply because the array is capable of holding a list of strings, such as frame labels).
That leads to my second clarification, which is that, generally speaking, you can always target whatever movie clip you like — be that the main timeline or a symbol — by using a valid reference to that movie clip. In the case of the main timeline, you can use
thisif the code is scoped to that timeline (in other words, if the code appears in a keyframe of that timeline). If the code is elsewhere, you can use_parentto “reach back” from whatever nested timeline you’re in. You can also use_root, as long as you understand what_rootreally means. In the case of movie clip symbols, you use their instance names.