AS3 - How to create a new MovieClip from externally loaded SWF - actionscript-3

I am exporting my animated characters from Flash Professional as a SWF to externally load them into AS3. I do not want to export them as SWC's because I have hundreds of these characters and only a small portion of them will be used at a given time.
It seems impossible to create multiple of these character MovieClips from the same loaded SWF since they are not SWC's I have no ActionScript linkage to be able to say
var myClip:MovieClip = new MyMovieClip();
I need to be able to make separate MovieClips from this same loaded character SWF. I essentially want to be able to say
var newMovieClip:MovieClip = otherMovieClip.clone();
Can this be done?

Would you be able to try this:
var newMovieClip:MovieClip = new (otherMovieClip as Object).constructor()
or
var className:String = getQualifiedClassName(otherMovieClip);
if(className)
{
var _class:Class = getDefinitionByName(className);
if(_class)
{
newMovieClip = new _class;
}
}

Related

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.

load an external swf (FlashPaper pdf) into a flash project

I have to do a very simple swf application able to show a series of pdf files.
Actually I was able to create on a single layer the menu interface (some buttons on frame 0 which redirect the user to other frames where the pdf should be showed).
Here my question:
I need a way to read the pdf inside the flash frame.
I've found a possible solution converting the pdf into an swf with FlashPaper 2
Now I wish to know how import the swf into the frame.
Reading some actionscript 3 guides I was able to create a container movieclip (a simple rectangle) into which I have loaded the swf with this code:
var swf:MovieClip;
var loader:Loader = new Loader();
var defaultSWF:URLRequest = new URLRequest("test.swf"); //test.swf is my converted pdf
loader.load(defaultSWF);
screen_01.addChild(loader); //screen_01 is the container rectangle converted to movieclip
I've used a container movieclip to mantain the other objects (menu buttons) on the frame, and ecause it helps with the swf positioning.
I seen it is possible also using loader.x and loader.y and it works.
Unfortunately I wasn't able to control width and height of the swf/pdf file (loader.width and loader.height exists but if used cause the swf will not loaded at all)
Solution:
I've found a possible solution at this page. The idea is to change swf scale only after the load process is complete (positioning can be done even before).
Anyway I had to use Actionscript 2 for this project because FlashPaper converted pdf doesn't work properly with AS3, I don't know why...
here the code:
//insert an emplty movieclip to load the swf, I've called it screen_01
var movLoad:MovieClipLoader = new MovieClipLoader();
var myListener:Object = new Object();
myListener.onLoadInit = function(thisMc:MovieClip) {
thisMc._height = 600;
thisMc._width = 900;
thisMc._x = 50;
thisMc._y = 30;
};
movLoad.addListener(myListener);
movLoad.loadClip("folder/flashpaper_converted_pdf.swf.swf",screen_01);
You can modify the size of the loader using scaleX and scaleY properties.
Keep them equals so the swf isn't stretched.
You may also want to listen to the COMPLETE event to do such a thing :
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
function onComplete(e:Event)
{
var loader:Loader = e.currentTarget.loader;
loader.scaleX = loader.scaleY = 2; //Double the size of the loaded swf
}

Access children of embedded aswf

I am embedding an swf file that has some children on its timeline. Like this:
[Embed(source="assets/skyscraper200x600.swf")]
private var Skyscraper :Class;
All children in the swf have an instance name, I double checked that when creating the swf in Flash CS5.
I am trying to access those children by name like this:
_bg = MovieClip(new Skyscraper());
_pig = MovieClip(_bg.getChildByName("chara_pig"));
_arrow = MovieClip(_bg.getChildByName("arrow_banner"));
However, both _pig and _arrow end up being null.
What's even stranger is that when I look at the Skyscraper object in the debugger, it shows a rather strange class name and a Loader as its only child (which in turn has no children). What's up with this?
.
I can access them like above if I do not embed the swf, but load it with a Loader. But I cannot do it in this case. I need to embed the swf.
So, how can you access children of embedded swfs?
I am not talking about accessing classes in the library of the embedded swf, but the instances on the timeline.
Here is a solution. You can also see the steps who helped me find this solution (describeType is your friend) :
public class Demo extends Sprite {
[Embed(source="test.swf")]
private var Test:Class
public function Demo() {
//first guess is that embed SWF is a MovieClip
var embedSWF:MovieClip = new Test() as MovieClip;
addChild(embedSWF);
//well, emebed SWF is more than just a MovieClip...
trace(describeType(embedSWF));//mx.core::MovieClipLoaderAsset
trace(embedSWF.numChildren);//1
trace(describeType(embedSWF.getChildAt(0)));//flash.display::Loader
var loader:Loader = embedSWF.getChildAt(0) as Loader;
//the content is not already loaded...
trace(loader.content);//null
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(){
var swf:MovieClip = loader.content as MovieClip;
var child:MovieClip = swf.getChildByName("$blob") as MovieClip;
//do nasty stuff with your MovieClip !
});
}
}
At the end of this tutorial http://jadendreamer.wordpress.com/2010/12/20/flash-as3-embedding-symbols-from-external-swf-game-tutorial there is an example of how it can be done
One solution is to embed the swf as an octet stream and reconstitute its bytes. However, I seem to remember reading somewhere that if you just set the mimeType to "application/x-shockwave-flash", you get a MovieClip that works as normal.

How to add all symbols in library folder to stage at runtime

I just submitted this question but i can't see if it posted anywhere, so I apologize if this is a duplicate.
For a Flash CS4 project, I am constantly importing new images, converting them to movieclips and storing them in the library under an "Ornaments" folder. All of these ornaments need to be on the stage in a certain place when the program is initialized. Instead of having to drag the new symbols onto the stage every time I add a new, is it possible to add all of the symbols in the "Ornament" library folder to the stage at runtime?
Thanks
You can do it in code if you wish, but you'd have to still add the names of the symbols to the code. That is, the folder is merely a convenience for organizing within the CS4 library and it does not translate to code (AFAIK).
To instantiate the item in AS3, simply right click the symbol in the library and check the box labelled "Export for ActionScript". If you can't see it, click the Advanced button. It will default the Class to the name of the symbol. That will be the class you can instantiate in ActionScript to put an instance on stage.
You could keep an array of the ornament names and loop through them adding them to the stage:
var ornaments:Array = [OrnamentGold, OrnamentSilver, OrnamentBronze];
for each(var ornament:Class in ornaments)
{
var ornamentClip:MovieClip = new ornament();
addChild(ornamentClip);
}
If you name all of your instances the same with only a trailing digit incremented, you can save yourself some time and just increment a single number:
const NUM_ORNAMENTS:int = 5;
for(var i:int = 0; i < NUM_ORNAMENTS; i++)
{
// ornaments are names Ornament0, Ornament1, Ornament2, etc. in the library
var ornamentClass:Class = new getDefinitionByName("Ornament" + i) as Class;
var ornamentClip:MovieClip = new ornamentClass();
addChild(ornamentClip);
}

Load AS2 SWF Into AS3 SWF and pass vars in URL

I've got an AS3 SWF that I'm going to be loading other SWFs into. These child SWFs all take a single parameter on the URL. I can't seem to get it working when loading an AS2 child, and it needs to be able to handle both.
so I have
var request:URLRequest = new URLRequest();
var loader:URLLoader = new URLLoader();
request.url = "http://domain/as2.swf?param=foo";
loader.load(request);
// etc on to the eventListeners, addChild, etc
When the as2 SWF gets loaded, it can't see the parameter I've passed to it. It's looking for _root.param. Am I doing this wrong or am I attempting the impossible?
EDIT: I should add that I can load a SWF with those URL params from an AS2 loader and it works just fine.
It's not trivial to communicate between AS2 and AS3 since they run in different virtual machines. Check this http://www.gskinner.com/blog/archives/2007/07/swfbridge_easie.html for some hints.
Edit: If you cannot change the loaded as2 content your only options is creating a 'wrapper' as2 loader that uses the linked example above to communicate with the as3 and interfaces with the loaded as2 content using _root.varname This is not pretty but it might just work.
It might be worth trying to assign the variables dynamically after the SWF has loaded but before you add it to the stage. Ie.
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, movieLoaded);
function movieLoadedHandler(event : Event) : void
{
var loaderInfo : LoaderInfo = event.target as LoaderInfo;
var clip : DisplayObject = loaderInfo.content;
for each(var prop in varsToTransfer)
{
clip[prop] = varsToTransfer[prop];
}
// add to parent
}
Let me know how that goes.
AS3 -> AS3
Movie 1(www.domain1.com):
Load the external movie when click a "buy" button...
buy.addEventListener(MouseEvent.CLICK,function(){
var ldr:Loader = new Loader();
var url:String = "http://www.domain2.com/movie.swf?a=b&c=d";
var urlReq:URLRequest = new URLRequest(url);
ldr.load(urlReq);
addChild(ldr);
});
Movie 2(http://www.domain2.com/movie.swf):
var mc:MovieClip = this as MovieClip;
var ldi:LoaderInfo = mc.loaderInfo;
var lobj:Object = ldi.parameters as Object;
for (var l in lobj) {
dumper.htmlText += l+" => "+lobj[l]+"<br />";
}
"dumper" is the name of the Dynamic Textbox field located in Movie2.
The output should look like:
a => b
c => d
Instead of looking for _root.param, use _root._url then parse out your parameters by hand.
var url: String = _root._url;
var param: String = 'param=';
var paramStart: Number = url.lastIndexOf(param);
var paramValue: String = url.substring(paramStart + param.length, url.length);
trace(paramValue);
SWFBridge is awesome and overkill for something like this.
You are doing it wrong.
"http://domain/as2.swf?param=foo"
Is a request for the file named as2.swf, on the server named domain. Any ?param=foo parameters that are part of that http request are lost when the request is complete. If the server needed to do something according to these variables, it would, but you are asking a .swf file to detect these variables, that's just silly.
Put a variable in your Global object (Global namespace) for the flash player, then when the as2 .swf is loaded into that flash player it will have access to the variable you set in your Global object.
I am not proficient in as2, but in as3, the Global object can be accessed with the this keyword, at the package level (probly is the same for as2, just dont worry about setting it at a package level).