Copy link to clipboard
Copied
Hi all, I have a question.
I'm creating interactions in Adobe Animate using AS3.
I have 3 moviclips each is a self contained game/interaction.
How can I script a button that will play one of the moviclips at random, then when the player comes back to main timeline and the button is pressed again the user is sent randomly to one of the other movieclips? I dont want the user to see the same moviclip twice in a row.
Hope you guys can help, thanks
John
Peace
Hello again,
Sorry for the late reply. Text will block clicks. If you're generating the text yourself then it's on a layer that is "higher" or above the shape. If you attach the click event to the shape then the text may intercept it. This happens to a lot of people that draw a button shape and then add text on the timeline in the layer above where the text interferes with the click.
When I'm generating dynamic text, I set the TextField property to .mouseEnabled = false; Try doing this to see if
...Copy link to clipboard
Copied
This is just a quick frame script assuming there's timeline clips named 'clip_1', 'clip_2' and 'clip_99', just for examples. It just has an array you can add as many clips to that you like (named anything) and it'll stop all other clips in the array while starting a different random clip that won't be the same clip. This is the easy way so it should be easy to follow (there's a million ways to do it).
Again assuming those clips and 'changeClipBtn' was the name of your button, just change to suit your needs. This is a script on frame 1 of the main timeline:
// keep track of the current clip
var lastClip:int = 0;
// filling an array with instance names on the timeline to choose between
// add as many as you like
var clips:Array = [ 'clip_1', 'clip_2', 'clip_99' ];// assuming on the main stage
// might want to iterate though clips turning their visible off, etc
// assign button handler, season name to taste
changeClipbtn.addEventListener( MouseEvent.CLICK, changeClipHandler );
function changeClipHandler(e:MouseEvent):void {
// assure clips contains something to assure no infinite loops
if ( clips.length == 0 ) { return; }// no clips, do nothing
// we at least have one clip, stop all clips
for ( var i:int = 0; i < clips.length; i++ ) {
root[ clips ].gotoAndStop(1);
}
// only a single clip? play it again
if ( clips.length == 1 ) {
this[ clips[0] ].gotoAndPlay(1);
return;
}
// if we get here we at least have 2 clips
// rand generate a number pointing to a spot in the array
var nextClip:int = Math.floor( Math.random() * clips.length );
// if the generated number is the same as the last number, generate again
while ( nextClip == lastClip ) {
nextClip = Math.floor( Math.random() * clips.length );
}
// just showing you the values
trace('nextClip:' + nextClip + ', lastClip:' + lastClip);
// track the new loading clip
lastClip = nextClip;
// here you can just play the clip or return the value, I'm asking it to play
root[ clips[nextClip] ].gotoAndPlay(1);
}
Copy link to clipboard
Copied
Thanks sinious, that will surely be a help to me, thanks again.
Copy link to clipboard
Copied
You're welcome and good luck!
Copy link to clipboard
Copied
Hi Sinious, I am trying to get the script to work. I have a question.
I have placed my moviclips in their own layer on the main timeline.
I was under the impression that I could make the movie clips and keep them in the library then play them from there. I see I am wrong in thinking this as I can only give the clips instance names when they are sitting on a timeline. For the button I have just created a button symbol and dropped this on the main timeline.
I have turned off the visibility of the clips at the start of the script.
I am getting this error:
TypeError: Error #1010: A term is undefined and has no properties.
at Untitled_1_fla::MainTimeline/changeClipHandler()
Sorry I cant upload the .swf, the forum here does not give me an option to upload files.
Copy link to clipboard
Copied
If you'd like to access the library then it can be a little complicated "looking" but it's possible.
The normal way to make a library item appear on stage is just open the properties on any library element, go in properties and check off the "Export for ActionScript" while giving it a valid "class" name (letters, numbers, try to stick with that). For example if I named my library item in Export for ActionScript to "myClip1" then to display it I would:
// make a new clip 'instance' of 'myClip1' from the Library
var clip1:MovieClip = new myClip1();
// add it to the stage to be visible
stage.addChild(clip1);
Here's a shot including the properties panel.
A few things to note. The drop-down in properties is set to make it a MovieClip as is the "Base Class" setting, so I must set the type in ActionScript (as you see highlighted) appropriately. In the code above the only extra thing is the stop() so it doesn't keep repeating the frame code. Also note that in the code I am only using the "Export for ActionScript" name, not the name of the library item. Run that and you'll see your clip appear.
To grab something dynamically based on a variable like you're doing makes use of the getDefinitionByName() function so you can use variables to specify the name, like in the loop where it uses an index on the clips array and returns the string: clips. Since getDefinitionByName returns a class you typically convert it to the proper type as well. Like so:
So your loop will look similar to this, assuming you have 3 clips in the library "clip1", "clip2", "clip99":
import flash.utils.getDefinitionByName;
stop()
// keep track of the current clip
var lastClip:int = 0;
var currentClip:MovieClip;
// filling an array with instance names on the timeline to choose between
// add as many as you like
var clips:Array = [ 'clip1', 'clip2', 'clip99' ];// assuming on the main stage
// assign button handler, season name to taste
changeClipbtn.addEventListener( MouseEvent.CLICK, changeClipHandler );
function changeClipHandler(e:MouseEvent):void {
// assure clips contains something to assure no infinite loops
if ( clips.length == 0 ) { return; }// no clips, do nothing
// stop current clip
currentClip.gotoAndStop(1);
// only a single clip? play it again
if ( clips.length == 1 ) {
currentClip.gotoAndPlay(1);
return;
}
// if we get here we at least have 2 clips
// rand generate a number pointing to a spot in the array
var nextClip:int = Math.floor( Math.random() * clips.length );
// if the generated number is the same as the last number, generate again
while ( nextClip == lastClip ) {
nextClip = Math.floor( Math.random() * clips.length );
}
// track the new loading clip
lastClip = nextClip;
// remove existing clip from the stage
stage.removeChild( currentClip );
// get a class reference to the new clip from the library
var clipClass:Class = getDefinitionByName( clip[ nextClip ] ) as Class;
// no class? do nothing
if ( ! clipClass ) { return; }
var currentClip = new clipClass() as MovieClip;
// add to stage
stage.addChild( currentClip );
// play clip
currentClip.play();
}
You can see the getDefinitionByName now. The class is retrieved from the library via the name you put in the array at the top (clip1, clip2, clip99 etc). If it finds a class via that name it is instantiated and added to the stage, and then told to play. It might look a little complicated but you should be able to tinker with it. It might give you an error (I did it off the top of my head, no Adobe Animate on this system at the moment) but I'm sure you can figure it out if it's just a typo.
Season to taste.
Copy link to clipboard
Copied
Hey, thanks sinious for the great help. I have yet to test this but looks great. I will post back.
Thanks
Copy link to clipboard
Copied
You're welcome, be sure to mark helpful/correct and good luck!
Copy link to clipboard
Copied
Hi Sinious, your help here is most generous. I am just getting my head around the functionality of the forums here and so failed to mark your content as useful. My bad.
I have been busy with work and so I do not have the script working yet but i am sure I will.
Pulling and displaying moviecips from the library was just the way I had planned to go. I have used your method to call a movieclip from the library. I am having trouble though scripting a button that is inside the movieclip that will make the timeline play. Is there a quick way to code a button using Code Snippets?
Thanks again for all your help.
Copy link to clipboard
Copied
Are you referring to a button inside the loaded SWF that should play the main timeline that loaded it? Or just a button that plays the timeline it's on?
(reply will be delayed, on vacation at the moment)
Copy link to clipboard
Copied
Hi Sinious, I was having trouble making a button inside the moviClip's timeline. I had used some text over a shape and this seemed to be the cause of my problems. When I removed the text the code for Tap Event worked fine.
I am now having trouble scripting another button on the same movieClip's timeline to remove the Clip from the stage.
I hope that you have a relaxing vacation.
Copy link to clipboard
Copied
Hello again,
Sorry for the late reply. Text will block clicks. If you're generating the text yourself then it's on a layer that is "higher" or above the shape. If you attach the click event to the shape then the text may intercept it. This happens to a lot of people that draw a button shape and then add text on the timeline in the layer above where the text interferes with the click.
When I'm generating dynamic text, I set the TextField property to .mouseEnabled = false; Try doing this to see if it solves your problem.
e.g.
yourNewTextField.mouseEnabled = false;
Then see if you can click on your button.
InteractiveObject - Adobe ActionScript® 3 (AS3 ) API Reference
Copy link to clipboard
Copied
Thanks Sinious i will put that to the test.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now