Im a total beginner at using AS3. I want to know is how does one duplicate a symbol and make it appear in the next frame.
example: when the user clicks on the symbol in that frame, the same symbol will appear in the next frame. If it is not possible then how does one move that symbol to the next frame.
Thank You in advance for answering.
You should probably avoid to use timeline keyframe to achieve this kind of thing. However, if you really need to do it this way, here what I would do :
First, make sure the MovieClip you want to clone has ActionScript linkage.
Then:
my_mc.addEventListener(MouseEvent.CLICK,onClick)
function onClick(e:MouseEvent):void{
var m:MovieClip = MovieClip(e.currentTarget);
var c:Class = Object(m).constructor;
var clone:MovieClip = new c() as MovieClip;
gotoAndStop(2);
addChild(clone);
}
This will add the clone to the stage, so if you go back to frame 1, you'll see the clone. There's no way to add an object to a specific timeline frame. If you want to achieve such a thing, you have to target a container on frame 2 and add to clone to the container.
something like this :
function onClick(e:MouseEvent):void{
var m:MovieClip = MovieClip(e.currentTarget);
var c:Class = Object(m).constructor;
var clone:MovieClip = new c() as MovieClip;
gotoAndStop(2);
myContainerOnframe2.addChild(clone);
}
Related
I have a problem that after a lot of searches I didn't manage to solve it.
I created 2 movie clips in the library (let say mc1 and mc2). Then I manually create another movie clip in timeline (using IDE), let say foo.
As background inside foo I use mc1 with instance name bg. In ActionScript I'm trying to replace the foo.bg with mc2.
Please note that I already exported mc1 and mc2 to first frame with classes mc1() and mc2().
I tried (without any luck) :
var mc1:movieClip = new mc1()
var mc2:movieClip = new mc2()
if (....)
{
foo.bg=mc2;
}
Thanks
Mistake №1: managing objects in display list is not the same thing as assigning variables.
Mistake №2: variable names and class name MUST be different. On a case-level, at least.
So, you need to do something like that:
var mc1:MovieClip = new MC1;
var mc2:MovieClip = new MC2;
// ...
// Delete existing background.
foo.removeChild(foo.bg);
// Set the new background.
foo.addChild(mc2);
foo.bg = mc2;
i am using AS3 to create a function that will automatically play a movieclip all the way through and then remove it. my project is going to have a lot of animated cutscenes, so id like to be able to call this function, use the cutscene id like as a parameter, and then move on to the next. the problem is, im trying to use the function multiple times in a row to play clips sequentially, but they're all playing at the same time. is there a fix, or a better way to do this altogether?
playClip(new a_walk); //find a way to make these stop playing at the same time
playClip(new a_door);
//a_walk and a_door are the AS linkage class names for the movieclips im referring to
function playClip (clip:MovieClip):void {
addChildAt(clip, 0);
clip.mask = myMask;
clip.x=412.4;
clip.y=244.5;
clip.addEventListener(Event.ENTER_FRAME, checkframes);
function checkframes(event:Event) {
if (clip.currentFrame == clip.totalFrames) {
//trace("wow! youre an idiot!");
if (clip.parent) {
clip.parent.removeChild(clip);
trace (100);
return;
}
}
}
}
Sounds like you want a mechanism to play a queue of MovieClips? If so, here is a way you can accomplish this:
//create an array with the clips you want to play (in order), in my example here, the items can be a MovieClip derived Class, or a MovieClip instance
var playQueue:Array = [a_walk, a_door];
//create a var to store the currently playing clip
var currentClip:MovieClip;
playNext(); //call this when you want the queue of clips to start playing
function playNext():void {
//if there was an item previously playing (currentClip has a value), stop it and remove it/dispose of it
if(currentClip){
currentClip.stop(); //stop it from playing
currentClip.addFrameScript(currentClip.totalFrames-1, null); //remove the frame script that was added
currentClip.parent.removeChild(currentClip); //remove it from the display
currentClip = null;
}
//check if there's anything left to play
if(playQueue.length < 1) return;
var nextItem:* = playQueue.shift(); //shift retrieves and removes the first item in the array;
if(nextItem is Class){
//if it's a class, instantiate it
currentClip = new nextItem();
}else{
currentClip = MovieClip(nextItem);
}
//initialize the movie clip
addChildAt(currentClip, 0);
currentClip.gotoAndPlay(1);
//this is just what you were doing before:
currentClip.mask = myMask;
currentClip.x=412.4;
currentClip.y=244.5;
//add a command on the last frame of the movie clip to play the next item in the queue
currentClip.addFrameScript(currentClip.totalFrames-1, playNext);
//addFrameScript is 0 based, so 0 would refer to the first frame. This is why we subtract 1 to get the last frame
}
I should note, that addFrameScript is an undocumented function. It serves as a nice shortcut so you don't have to have an ENTER_FRAME listener checking currentFrame vs. totalFrames. Being undocumented however, one can not count on it's continued existence in future versions of the Flash/AIR runtimes (though it's been around for a long long time)
note
This answer is a work in progress. I'm waiting on a response from the OP.
// playClip(new a_door); don't call this yet, or they will just both play.
var clipData:CustomClass = new CustomClass(); // add an instance of a custom class to hold the value of the movie
//clip being played (so that you can use this value later in the event handler.)
// it will also hold a value of the next clip
clipData._currentClip = a_walk;
clipData._nextClip = a_door;
playClip(new a_walk);
function playClip (clip:MovieClip):void {
addChildAt(clip, 0);
clip.mask = myMask;
clip.x=412.4;
clip.y=244.5;
clip.addEventListener(Event.ENTER_FRAME, checkframes);
}
function checkframes(event:Event) {
if (clipData._currentClip.currentFrame == clipData._currentClip.totalFrames) {
//trace("wow! youre an idiot!");
if (clipData._currentClip.parent) {
playClip(clipData._nextClip);
clipData._currentClip.parent.removeChild(clipData._currentClip);
clipData._currentClip = clipData._nextClip; // moves the clips down
//clipData._nextClip = here we have
//a problem. Do these clips play in a set
//order, first to last? Or do the play out of
//order jumping back and forth? If so, how
//are you planning on controlling which clip
//plays next?
trace (100);
return;
}
}
}
I haven't checked this in Flash yet to see if it works, but I noticed that you are defining a function inside another function, which I don't think is good practice, so this might clean things up for you. Give it a try and let us know.
I'll try to fix my code above when I get a chance. In the meantime, you answered my question about playing the clips in order, so a simple solution would be to put all the clips in an array and then play them by playClip(clipArray[i]) and then when the clip ends and gets removed, do i++ and call the same function playClip(clipArray[i]) which will play the next clip in the array.
I'm fairly new at ActionScript 3 but I am working on it and trying to learn by reading and modifying ActionScript source codes.
So far so good, however I stumbled upon one problem which I seemingly can't solve by myself. It should be faily simple for you guys tho.
The situation:
I got one "object" which is clickable and gives a random value which is also being saved in a variable.
I got another "object" which does the same thing but only has a different name.
I want the variable from the first object to be passed to the second one, how can I do it?
One way to pass values relies on using references to objects...
// mc1 and mc2 exist as movieclips on the stage
mc1.addEventListener( MouseEvent.CLICK, onClick );
mc2.addEventListener( MouseEvent.CLICK, onClick );
function onClick( event:MouseEvent ):void
{
// reference clicked movieclip through click target
var mc:MovieClip = event.target as MovieClip;
// if our clip matches one, assign the other clip the value.
if ( mc === mc1 )
{
mc2.value = mc.value;
}
else if ( mc === mc2 )
{
mc1.value = mc.value;
}
}
There's a thousand ways to pass references around, and this is just one.
OK guys let me show you the important parts of the code (cant show it all since I paid for it and I don't know whether the author woudl be OK with me publishing all of it).
I got these two objects there. When I click on one of the objects (which is a DICE), it gives me this code basically
var faceValue:int = 6;
// Add mouse click functionality to roll the die
addEventListener(MouseEvent.CLICK, onClickDie, false, 0, true);
mouseChildren = false;
buttonMode = true;
function onClickDie(e:MouseEvent):void {
removeEventListener(MouseEvent.CLICK, onClickDie);
buttonMode = false;
// Initiate the roll-out sequence
if(faceValue == 6) {
gotoAndPlay("rollout6");
etc...
Then somewhere in the frame where it is SPINNING the dice it is randomizing a number and save it into facevalue
// Calculate a random face value between 1 and 6
faceValue = 1 + Math.floor(Math.random()*6);
// Initiate the roll-in sequence
if(faceValue == 6) {
gotoAndPlay("rollin6");
...etc
Now how can I get the randomized facevalue from the spinning the dice frame to pass it to the other dice?
Currently I have an intro screen to my flash file which has two objects.
A button which will load an external flash file using:
var myLoader:Loader = new Loader();
var url:URLRequest = new URLRequest("flashgame.swf");
The second thing is a Numeric Stepper, which will be from 1 to 10. If the user selects a number e.g. 3 then the game speed I have set in the flashgame.swf should be changed
Such as:
var gameSpeed:uint = 10 * numericStepper.value;
But I think my problem is coming into place because the stepper and gamespeed are from different files.
Anyone got any idea please?
I have also tried creating a stepper in the game file and used this code:
var gameLevel:NumericStepper = new NumericStepper();
gameLevel.maximum = 10;
gameLevel.minimum = 1;
addChild(gameLevel);
var gameSpeed:uint = 10 * gameLevel.value;
For some reason the stepper just flashes on the stage, no errors come up and the game doesn't work
When you execute you code, the stepper has no chance to wait for user input.
There is no time between theese two instructions.
addChild(gameLevel);
var gameSpeed:uint = 10 * gameLevel.value;
You should wait for user input in your NumericStepper, and then, on user event, set the game speed.
Edit: Yeah I know it's kinda sad to type out all this code (especially since some people wouldn't even be grateful enough to say thanks) but I think this question is important enough to justify the code as it may be helpful to others in future also.
Hi,
You were close. In your game file you could have put a var _setgameSpeed and then from Intro you could adjust it by flashgame._setgameSpeed = gameSpeed; It's a bit more complicated though since you also have to setup a reference to flashgame in the first place. Let me explain...
Ideally you want to put all your code in one place (an .as file would be best but...) if you would rather use timeline then you should create a new empty layer called "actions" and put all your code in the first frame of that.
Also change your button to a movieClip type and remove any code within it since everything will be controlled by the code in "actions" layer. In the example I have that movieclip on the stage with instance name of "btn_load_SWF"
Intro.swf (Parent SWF file)
var my_Game_Swf:MovieClip; //reference name when accessing "flashgame.swf"
var _SWF_is_loaded:Boolean = false; //initial value
var set_gameSpeed:int; //temp value holder for speed
var swf_loader:Loader = new Loader();
btn_load_SWF.buttonMode = true; //instance name of movieclip used as "load" button
btn_load_SWF.addEventListener(MouseEvent.CLICK, load_Game_SWF);
function load_Game_SWF (event:MouseEvent) : void
{
//set_gameSpeed = 10 * numericStepper.value;
set_gameSpeed = 100; //manual set cos I dont have the above numericStepper
if ( _SWF_is_loaded == true)
{
stage.removeChild(swf_loader);
swf_loader.load ( new URLRequest ("flashgame.swf") );
}
else
{ swf_loader.load ( new URLRequest ("flashgame.swf") ); }
swf_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, Game_SWF_ready);
}
function Game_SWF_ready (evt:Event) : void
{
swf_loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, Game_SWF_ready);
//Treat the Loader contents (flashgame.swf) as a MovieClip named "my_Game_Swf"
my_Game_Swf = swf_loader.content as MovieClip;
my_Game_Swf.gameSpeed = set_gameSpeed; //update gameSpeed variable in flashgame.swf
//also adjust SWF placement (.x and .y positions etc) here if necessary
stage.addChild(my_Game_Swf);
_SWF_is_loaded = true;
}
Now in you flashgame file make sure the there's also an actions layers and put in code like this below then compile it first before debugging the Intro/Parent file. When your Intro loads the flashgame.swf it should load an swf that already has the code below compiled.
flashgame.swf
var gameSpeed:int;
gameSpeed = 0; //initial value & will be changed by parent
addEventListener(Event.ADDED_TO_STAGE, onAdded_toStage);
function onAdded_toStage (e:Event):void
{
trace("trace gameSpeed is.." + String(gameSpeed)); //confirm speed in Debugger
//*** Example usage ***
var my_shape:Shape = new Shape();
my_shape.graphics.lineStyle(5, 0xFF0000, 5);
my_shape.graphics.moveTo(10, 50);
my_shape.graphics.lineTo(gameSpeed * 10, 50); //this line length is affected by gameSpeed as set in parent SWF
addChild(my_shape);
}
The key line in intro.swf is this: my_Game_Swf.gameSpeed = set_gameSpeed; as it updates a variable in flashgame.swf (referred as my_Game_Swf) with an amount that is taken from a variable in the Parent SWF.
This is just one way you can access information between two separate SWF files. Hope it helps out.
I am trying to give my "buttons" a bounce in effect using the tween class. I am also trying to make my code more efficent by using a function to handle this effect for all my buttons.
var MusicClip:MovieClip = new music_mc();
var MoviesClip:MovieClip = new movie_mc();
var GameClip:MovieClip = new game_mc();
MusicClip.y = 63;
MusicClip.x = 577;
MoviesClip.y = 87;
MoviesClip.x = 401;
GameClip.y = 75;
GameClip.x = 151;
addChild(MusicClip);
addChild(MoviesClip);
addChild(GameClip);
This is where I am having a hard time. I thought I had to tween both the
scaleX and scaleY for all three MovieClips, but the button just appears on the
stage and doesn't animate in. Also if I can put this code in a function so I
don't have to write it for every button (and future buttons) that would be great.
var scaleTween:Tween=new Tween(MusicClip,"scaleX",Elastic.easeOut,0,1,1,true);
var scale2Tween:Tween=new Tween(MusicClip,"scaleY",Elastic.easeOut,0,1,1,true);
I am not getting any error but there is no bouncing in effect.
You need to assign listeners to your MovieClips that will perform an action when you do something. You can use a single event handler for all of your MovieClips:
MusicClip.addEventListener(MouseEvent.MOUSE_OVER,bounceButton);
MusicClip.addEventListener(MouseEvent.MOUSE_OVER,bounceButton);
MoviesClip.addEventListener(MouseEvent.MOUSE_OVER,bounceButton);
function bounceButton(event:MouseEvent):void
{
var scaleTween:Tween=new Tween(event.target,"scaleX",Elastic.easeOut,0,1,1,true);
var scale2Tween:Tween=new Tween(event.target,"scaleY",Elastic.easeOut,0,1,1,true);
}
Note that rather than specifying any one MovieClip as the tween target, you are using event.target, which will refer to the MovieClip you have rolled over.
On an unrelated note, it is good practise to start instance names with a lower case letter. This helps to distinguish them from class names which by convention have uppercase letters to start each word:
var myVariable:MyClass;