example image
Very new to AS3. Sorry if this question is really basic, I tried looking around for the right answer but only found semi-related questions. Please help!!
Objective: I want multiple rollover MovieClips on the same stage that play out their animations independently.
So far, I have only 1 MovieClip object that behaves properly. If I add another, the first one behaves properly but the second doesn't appear at all. I understand that it's probably only calling the instance that I first dropped into the stage and that I need to change my code to have a "master" or parent MovieClip and that the instances should be the children, but I'm not sure how to write that in code. Eventually, the idea is that I add my children movieclips, and then slightly change the content in each clip.
My code so far:
import flash.events.MouseEvent;
clip_boxes.removeEventListener(MouseEvent.ROLL_OUT, clipOut);
clip_boxes.addEventListener(MouseEvent.ROLL_OVER, clipOver);
function clipOver(event:MouseEvent):void {
clip_boxes.addEventListener(MouseEvent.ROLL_OUT, clipOut);
clip_boxes.removeEventListener(MouseEvent.ROLL_OVER,clipOver);
clip_boxes.gotoAndPlay("Over");
};
function clipOut(event:MouseEvent):void {
clip_boxes.addEventListener(MouseEvent.ROLL_OVER, clipOver);
clip_boxes.removeEventListener(MouseEvent.ROLL_OUT, clipOut);
clip_boxes.gotoAndPlay("Out");
};
There are a few ways you can do this. I'll list in order of worst to best.
Manually add listeners to each instance.
When you drag a new MovieClip onto the timeline, you need to give it an instance name (found in the properties panel). I'm not sure if clip_boxes is a parent timeline that you intend to have all your movie clips on, or if it is one of your movie clips itself.
Assuming you have 3 clips with the instance names: MC1,MC2,MC3, you could do this (on the first frame of the timeline that contains them)
MC1.addEventListener(MouseEvent.ROLL_OVER, clipOver);
MC2.addEventListener(MouseEvent.ROLL_OVER, clipOver);
MC3.addEventListener(MouseEvent.ROLL_OVER, clipOver);
//If you had a whole bunch, you could also use a loop to add all the listeners
//you use event.currentTarget to get a referce to the object the listener was attached to - this way you only need this one handler function
function clipOver(event:MouseEvent):void {
MovieClip(event.currentTarget).addEventListener(MouseEvent.ROLL_OUT, clipOut);
MovieClip(event.currentTarget).gotoAndPlay("Over");
};
function clipOut(event:MouseEvent):void {
MovieClip(event.currentTarget).removeEventListener(MouseEvent.ROLL_OUT, clipOut);
MovieClip(event.currentTarget).gotoAndPlay("Out");
};
Use Inheritance
This would involve creating a base class file (.as file) that you can then attach to all your MovieClips so they inherit all the code within. Here is an example of a class file that would do this for you: (lets assume this is a file called SubClass.as in your root directory)
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class SubClass extends MovieClip {
public function SubClass(){
this.addEventListener(MouseEvent.ROLL_OVER, rollOver,false,0,true);
}
public function rollOver(event:MouseEvent):void {
this.addEventListener(MouseEvent.ROLL_OUT,rollOut,false,0,true);
this.gotoAndPlay("Over");
}
public function rollOut(event:MouseEvent):void {
this.removeEventListener(MouseEvent.ROLL_OUT,rollOut,false);
this.gotoAndPlay("Out");
}
}
}
Now, when you create your movieClips (or right click in the library and select properties), you can set a baseClass for them. If you set the base class to the class above, they automatically use the code above and have the mouse over/out attached. (as long as they have the Out/Over frame labels it will just work).
Can you also post the code where you add clip boxes to the stage? Did you add them in the GUI by dragging and dropping or in code?
If so, you might need to make instances of each of the clip boxes inside the larger movieclip that contains all of them together. Then you'll need to refer to each one with clip_boxes.box1, etc.
EDIT:
Oh, I see you had an image there. My bad. Make sure you give each clip box its own unique instance name. You'll need to have clip_box_1, clip_box_2, etc. Then in code you use clip_box_1.addEventListen.....etc.
Related
I saw plenty of questions that asked how to make a button in a movie clip that leads to a frame in the main timeline, and took a look at them. But is it different if you want to go to a random frame in a specific set of frames? I've never really used AS3 aside from simple things like stop(); or gotoAndPlay.
Here's what my main timeline looks like at the moment:
Here's the code I've got so far by using Google:
var frameB:Array=[1,28,45,56,71,91,106,126];
blue_circle1.addEventListener(MouseEvent.CLICK, choose);
function choose1(event:MouseEvent):void {
var randomFrame:Number = frameB[Math.floor(Math.random() * frameB.length)];
trace(randomFrame);
gotoAndPlay(randomFrame);
}
The code works fine when I use it on the rotation buttons in the main timeline. But it doesn't work when I put it in a button in a movie clip. I need to change it so it works. If there is a better way of doing this, I'm willing to try it.
Edit: I should clarify things more. I got rectangle on wheels that moves left to right. It does this in a movie clip. I want the button to move with it. But when I place the button into said movie clip, the code on the button stops working. I hope I didn't end up making things more confusing.
When you place the button and/or code inside the movieClip it changes the movieClip that gotoAndPlay() is referring to. You need to specify which movieClip you are calling gotoAndPlay() on. For the main timeline gotoAndPlay() works, but inside a movieClip you must use this:
parent.gotoAndPlay(randomFrame);
Or you may need to set parent's type to a MovieClip like this:
MovieClip(parent).gotoAndPlay(randomFrame);
However, it's best to use external .as files as it gives you the most control over your code.
Save the code below in a file called 'MyFlashAnimation.as'
Create a folder called 'mycodefolder' and put it in the same directory/folder as your .fla.
Use the 'MyFlashAnimation.as' as your document class. In the Flash/Animate IDE find the Properties panel, then the Publish section
In the Publish section where it says 'Class' enter: mycodefolder.MyFlashAnimation (do not add the .as)
CODE:
package mycodefolder {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class MyFlashAnimation {
private var animationClip:MovieClip;
private var blueCircle1:Button;
private var frameB:Array = [1,28,45,56,71,91,106,126];
// constructor
public function MyFlashAnimation() {
// this your main robot/car animation
// this assumes animation_clip is on the main stage
animationClip = this.animation_clip;
// this is your button. this assumes blue_circle1 is a child of
// your animation_clip. update the path if necessary.
// for example, it might be: animationClip.robot_body.blue_circle1
blueCircle1 = animationClip.blue_circle1;
// add listener
blue_circle1.addEventListener(MouseEvent.CLICK, choose);
}
function choose1(event:MouseEvent):void {
var randomFrame:Number = frameB[Math.floor(Math.random() * frameB.length)];
trace(randomFrame);
// tell animation clip to gotoAndPlay
animationClip.gotoAndPlay(randomFrame);
}
}
}
That should work. If you have all your movieClip paths correct.
"The code works fine when I use it on the rotation buttons in the main timeline. But it doesn't work when I put it in a button in a
movie clip."
What is the instance name of the MClip you paste the button into? That MC name will "add" to the final path of your button.
Examples:
(1) If your blue_circle1 on stage (you already can do this) :
blue_circle1.addEventListener(MouseEvent.CLICK, choose);
versus...
2) If your blue_circle1 is inside another MClip (with example name as: thingMC) :
thingMC.blue_circle1.addEventListener(MouseEvent.CLICK, choose);
I am not a programmer, so please forgive me if my question is too noobish.
I created a MovieClip in my library called "skill". Then I added three instances of that MovieClip into my stage called "skill_01", "skill_02", and "skill_03" respectively. I selected all three instances and created another MovieClip called "diagram" to nest them inside it. I will later add more skill instances inside this MovieClip called "diagram" but for now, I need the basics to work with three instances.
The main timeline or stage only has 1 frame, and so does the "diagram" MovieClip instance. However, the skill instances all have two frames: in frame 1 I have an PNG image showing them as being locked/offline, and in frame 2 I have another PNG showing them as unlocked/online. I need to be able to toggle them by clicking and right clicking on them, just like in the example below (see link)
I am trying to make it so that when you left click the skill instances they toggle to Online/Unlocked by switching to the PNG image in frame 2, and when you right click them, it goes back to frame 1 (Offline/Locked). I've tried several different lines of code, including the ones recommended by Adobe itself, and others, and I can't figure out what I'm doing wrong. It will go to frame 2 and refuse to go back to frame 1 when right clicked.
This is the code I have in the MovieClip:
stop();
skill_01.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame);
function fl_ClickToGoToNextFrame(event:MouseEvent):void
{
gotoAndStop(2);
}
This part of the code doesn't work:
skill_01a.addEventListener(MouseEvent.RIGHT_CLICK, fl_ClickToGoToPreviousFrame);
function fl_ClickToGoToPreviousFrame(event:MouseEvent):void
{
prevFrame();
}
Screenshot 1:
gyazo (dot) com/e622baee46c3fabbd8c9a8d2df8396fe
Screenshot 2:
gyazo (dot) com/1b360716a5d243aa74e2be4127fe9a5b
(Sorry for typing the links like that, it won't let me add more than 1 link because I just signed up to this Forum)
For more context, I am trying to make a Skill Tree, that works similar to this one: http://www.dungeonsanddevelopers.com/#__6_Your
I will appreciate any help figuring this out!
if you have named your movieclip, skill_01, so what is the skill_01a ?
also add your event listener and its callback function in to the movieclip's parent and inside the callback function, for accessing the event owner, use
// stop(); not necessary to call stop if you have only 1 frame
with (this.diagram) {
skill_01.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame);
skill_02.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame);
skill_03.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame);
skill_04.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame);
skill_01.gotoAndStop(1);
skill_02.gotoAndStop(1);
skill_03.gotoAndStop(1);
skill_04.gotoAndStop(1);
}
function fl_ClickToGoToNextFrame(event:MouseEvent):void
{
if (MovieClip(event.target.parent).currentFrame == 1)
MovieClip(event.target.parent).gotoAndStop(2);
else
MovieClip(event.target.parent).gotoAndStop(1);
}
Edit: when an event is dispatched from clicked movieclip, only the last movieclip inside hierarchy tree will be passed as event.target in your exaple, that can be skill_01 (if currentframe is 1) or skill_1a (if currentframe is 2) athwart the question body, you have not only a png image inside skill's frame 1 and 2, they are movieclip's and will be returned as event.target. but if you only put your bitmaps (locked.png & unlocked.png) instead of skill_01 and skill_01a, the previous code works fine. bitmaps does not capture event so its parent is who accepted click event and its all a little confusing, i'm not good at explain
if its hard to comprehend
we shall use some thing like it, easier but larger code
with (this.diagram) {
skill_01.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame_s1);
skill_02.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame_s2);
skill_03.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame_s3);
skill_04.addEventListener(MouseEvent.CLICK, fl_ClickToGoToNextFrame_s4);
skill_01.gotoAndStop(1);
skill_02.gotoAndStop(1);
skill_03.gotoAndStop(1);
skill_04.gotoAndStop(1);
}
function fl_ClickToGoToNextFrame_s1(event:MouseEvent):void {
toggle_buttons(skill_01);
}
function fl_ClickToGoToNextFrame_s2(event:MouseEvent):void {
toggle_buttons(skill_02);
}
function fl_ClickToGoToNextFrame_s3(event:MouseEvent):void {
toggle_buttons(skill_03);
}
function fl_ClickToGoToNextFrame_s4(event:MouseEvent):void {
toggle_buttons(skill_04);
}
function toggle_buttons(button:MovieClip):void
{
if (button.currentFrame == 1)
button.gotoAndStop(2);
else
button.gotoAndStop(1);
}
I have four movieclips (the player, one arm, another arm, and a weapon) the arms are placed to player and the weapon is placed to the arms. The player should have one arm that displays below it. And the weapon and the other arm that should display on top of it.
However, I have two arms as two different movieclips but they both have the same exact code. If I kept both in the same movieclip, both arms would display on top the player or both would display below the player. And you can't have one movieclip splitting into two layers. And you can't have two movieclips sharing the same class.
So I would like to know if I can make these two arms share the same code without having to write it twice.
The cleanest approach would be to make a base class. You can make a PlayerArmBase.asfile beside your .fla file, and have it look something like this:
package {
import flash.display.MovieClip;
import flash.events.Event;
public class PlayerArmBase extends MovieClip {
public function PlayerArmBase(){
//don't do anything until this item has been added to stage/timeline
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage, false,0,true);
}
protected function addedToStage(e:Event):void {
//this is the equivalent of where timeline code runs
//put your code here for your arms
//for example:
this.addEventListener(Event.ENTER_FRAME, enterFrame, false, 0, true);
}
protected function enterFrame(e:Event):void {
//do something every frame tick like point to the mouse position
}
}
}
Now, you can make both your arms extend this base class. To do so, right click each arm in flash pro, and go their properties. Check the "Export For Actionscript" check box in the advanced settings, then in the "Base Class" field type the name of your class.
Now all the code in that class will apply to both arm MovieClips.
Alternatively, you could put all the common code in the base class, then make another 2 classes (one for each arm) and put specific code in those and have them extend the base class. This is the same as the graphic above, except instead of the base class field, put LeftArm in the class field.
package {
import flash.events.Event;
public class LeftArm extends PlayerArmBase {
public function LeftArm(){
}
//we can override the addedToStage function from the base class
override protected function addedToStage(e:Event):void {
super.addedToStage(e); //call the base class version of this function
//do stuff specific to the left arm
}
}
}
This way you have code specific to each arm in it's own class, but have all the common code in 1 place. Super classes can access all functions and vars that are declared with the public or protected keywords. protected is like private except super classes can still access it. private can only be used in the class you defined it in.
Like I had said in the comments, I don't like to code inside the MovieClips, but if you prefer working in that way, do the next:
Put the code inside an empty MovieClip, then put that MovieClip inside each arm MovieClip and make a variable that reference to the parent to do the transformations that you need.
Here you have an example
I have a class called "airport" which extends movieclip. I have, successfully, managed to add a mouseclick-eventlistener for every object of the class that i create.
When I click on one of the objects, I am supposed to enter frame 2 on the main timeline.
I've tried to use the following code inside the class:
this.addEventListener(MouseEvent.CLICK, clickHandler);
private function clickHandler(evt:MouseEvent):void
{
MovieClip(parent).nextFrame();
}
When I click on one of the objects, I don't enter frame 2, but the whole screen goes blank. Any ideas? Thanks for advice.
PS: If you request more of my code to provide an answer, I would be happy to provide it.
Whatever 'this' is isn't a direct child of the main timeline. Try this:
private function clickHandler(evt:MouseEvent):void {
MovieClip(root).nextFrame();
}
Oh..I just found the error. In my code I used the line
this.parent.visible = false
to hide the objects when I entered next frame.
What I did not know was that this also would hide every other movieclip, which results in the screen beeing totally white.
I'm trying to create a disclaimer link that, when moused-over, a movie clip (disclaimer window) will show-up on the swf. How do I do this in AS3, please?
I'm new, and I've only gotten this far:
import flash.events.MouseEvent;
import flash.ui.Mouse;
addEventListener(MouseEvent.MOUSE_OVER,showOptions);
function showOptions (e: MouseEvent): void {
}
You can load your disclaimer window movieclip dynamically from your library like so:
function showOptions(e:MouseEvent):void{
var disclaimer:MovieClip = new disclaimerMC();
disclaimer.name = "disclaimer"; //give disclaimer name in case used later
disclaimer.x = 100; //set coordinates of movieclip
disclaimer.y = 100;
this.addChild(disclaimer); //add the disclaimer to the screen
}
Make sure that you go to your disclaimer movieclip in the library, right-click it, go to properties / linkage, and change the Class field. In my example, I changed the Class field to disclaimerMC.
It might also be nice to let Flash know which movieclips the EventListener should apply to. The way your code is now, mousing over anything would call showOptions. As you probably don't want that, you can say
disclaimerLink.addEventListener(MouseEvent.MOUSE_OVER,showOptions);
So then, only when you mouse over disclaimerLink will disclaimer show.
Alternatively, if the disclaimer window will always appear and disappear in the same place, it is quicker to change its transparency value. Your MOUSE_OVER and MOUSE_OUT functions can call disclaimer.alpha=100; and disclaimer.alpha=0;, respectively.