Actionscript, load random Movie Clip into Scene - actionscript-3

I'm making a simple flash shooting gallery animation with about 5 targets on screen but I am useless at action script.
I have the main scene and 5 Target movie clips in an array. I would like to...
-> Start Animation -> load random clip -> play random clip till end-> generate new random clip -> Repeat with Delay Offset....
So far I have the following:
function getRandomLabel():String {
var labels:Array = new Array("Tar1", "Tar2", "Tar3", "Tar4", "Tar5");
var index:Number = Math.floor(Math.random() * labels.length);
return labels[index];
}
this.gotoAndStop(getRandomLabel());
}
This is working... but I would like to add a delay and no repeat to this...

Ok, lets do it.
// If you need to avoid playing the same movie two times.
var lastLabel:*;
// The list of labels.
var Labels:Array = ["Tar1", "Tar2", "Tar3", "Tar4", "Tar5"];
function playRandom():*
{
do
{
// Get a random index.
var anIndex:int = Math.random() * Labels.length;
}
while (Labels[anIndex] == currentLabel);
// Keep the current label in the variable.
currentLabel = Labels[anIndex];
gotoAndStop(currentlabel);
}
function playNext():void
{
// 1000 milliseconds = 1 second delay.
setInterval(playRandom, 1000);
}
Then. At the end of each of your movie clips you need to correctly call the playNext method. If these movies are in the same timeline, as the code above, just call playNext(); If they are separate MovieClip objects, it will probably be (parent as MovieClip).playNext(); I cannot really tell because I don't know the structure of your movie. You will probably need to read the following to understand: http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3e.html

Related

AS3 MOVING OBJECT ON SPECIFIC FRAME

so i've been working on this game for a week now and i dont have any coding background at all so im trying to find tutorial here and there.. then i come up with this problem ...
so what i wanna do is move the object (CHARA) to the right when i hit frame 80 inside (CHARA,which is a nested movieClip with 99 frames btw ) then move it back to original position when i hit frame 99...
the problem is anything i do doesn't make my object move at all (movieClip still played btw) what did i do wrong here? did i just put the code at the wrong position ?? (CHAR is moved only if i put the code x= directly inside frame 80 but i try using class here)
here is my code,sorry i know its messy its my first code i try my best here
package {
public class Main extends MovieClip {
public var CHARA:CHAR = new CHAR;//my main char
public var rasen:Rasen_button = new Rasen_button;//the skill button
public var NPCS:NPC = new NPC;// the npc
public function Main() {
var ally:Array = [265,296];//where me and my ally should be
var jutsu:Array = [330,180];// where the buttons should be
var enemy:Array = [450,294];//where the enemies should be
addChild(NPCS);
NPCS.x = enemy[0];
NPCS.y = enemy[1];
NPCS.scaleX *= -1;
addChild(rasen);
rasen.x = jutsu[1];
rasen.y = jutsu[0];
addChild(CHARA);
CHARA.x = ally[0];
CHARA.y = ally[1];
rasen.addEventListener(MouseEvent.CLICK, f2_MouseOverHandler);
function f2_MouseOverHandler(event:MouseEvent):void {
CHARA.gotoAndPlay(46); //here is the problem
if (CHARA.frame == 80)
{
CHARA.x = ally[1]; //just random possition for now
}
}
}
}
}
any suggestions?
Your if statement is inside a click handler (f2_MouseOverHandler), so it only gets executed when a user clicks rasen, not necessarily when the playback reaches frame 80. This is a common beginner mistake related to timing and code execution. The most straight forward solution is to write some code that will execute every frame using an ENTER_FRAME handler:
rasen.addEventListener(MouseEvent.CLICK, f2_MouseOverHandler);
function f2_MouseOverHandler(event:MouseEvent):void {
CHARA.gotoAndPlay(46); //here is the problem
// add an ENTER_FRAME handler to check every frame
CHARA.addEventListener(Event.ENTER_FRAME, chara_EnterFrameHandler)
}
function chara_EnterFrameHandler(event:Event):void {
if (CHARA.currentFrame == 80)
{
CHARA.x = ally[1]; //just random possition for now
// remove the ENTER_FRAME after the condition is met
// so it stops executing each frame
CHARA.removeEventListener(Event.ENTER_FRAME, chara_EnterFrameHandler);
}
}

AS3: how do i stop two of the same function from playing at once?

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.

Actionscript 3 - Passing one variable from one object to another in the same project

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?

Particle Animation as3 Layering

I have battled through several tutorials to come up with the perfect particle snow effect. The only thing I need to do now is duplicate the particle effect and have a second version of it play between my background and foreground. The original I still want to keep as the top most layer. I tried wrapping the code in a function and making two of them with different names, but I got a bunch of weird errors. So instead of ruining what I already have I came here to ask for any advice on the situation. Here is my code. I am using the Greensock animation library to handle my timeline and animation.
import com.greensock.*;
import com.greensock.easing.*;
addChildAt(MC_BG, 0)
addChildAt(MC_FG, 2)
var tl:TimelineMax=new TimelineMax({paused:false});
function createFlake(offset) {
//create a flake (attach symbol in library with Class flake) and position on stage
var flake:Flake = new Flake();
flake.y=-50;
flake.x=randomRange(-10,1090);
flake.alpha=0;
addChild(flake);
//create timeline for each flake
var nestedTl:TimelineMax = new TimelineMax();
//how much wiggling / zig zagging
var wiggle:Number=randomRange(15,35);
//zig or zag?
wiggle=Math.random() > .5?- wiggle:wiggle;
//how fast and big
var speed:Number=randomRange(5,15);
//fade and grow
nestedTl.insert(TweenMax.to(flake, .5, {alpha:randomRange(.5,1), scaleX:speed, scaleY:speed}));
//go down
nestedTl.insert(TweenMax.to(flake,speed, {y:800}));
//zig zag
nestedTl.insert(TweenMax.to(flake, speed*.15, {x:String(wiggle), repeat:Math.floor(randomRange(1,4)), yoyo:true, ease:Sine.easeInOut}));
tl.insert(nestedTl, offset);
}
//generate random num between a min and max value
function randomRange(min:Number, max:Number):Number {
return min + (Math.random() * (max - min));
}
function init() {
//create a bunch of flakes and add them to timeline
for (var count:Number = 0; count<10000; count++) {
var offset = count * 0.075;
createFlake(offset);
}
}
init();
Any help would be greatly appreciated.
The answer was so simple I completely overlooked it. I made 3 blank Movie Clips, and in each of them I put a slightly modified version of this code. Then I put each movie clip on a layer in between what I wanted, and Bob's your uncle, it worked.

Using a Numeric Stepper from one Flash file to affect gamespeed in an external Flash file? Actionscript 3.0

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.