How to create a series of class instances in a for loop, as3 - actionscript-3

In my library I have a bunch of classes named tip1, tip2, tip3, tip4...and so on. Is it possible to create one instance of each on the stage using a for loop? I tried this but it didn't seem to work.
var tips:int = 12;
for(var i:int = 1; i<=tips; i++){
var tipName:String = "tip"+i
var tip:MovieClip = new tipName();
tip.name = "tip" + i
tip.x = stage.width;
tip.y = 0;
addChild(tip);
}
Any help would be appreciated. Thanks!

You were missing the "getDefinitionByName" part.
// Up top
import flash.utils.getDefinitionByName;
// Down below
var tips:int = 12;
for (var i:int = 1; i < tips; ++i ) {
var myClass:Class = getDefinitionByName('tip' + i) as Class;
var tip:Object = new myClass();
tip.name = "tip" + i;
....
}

Instead of
var tip:MovieClip = new tipName();
Try (written from memory)
var clazz:Class = getDefinitionByName(tipName) as Class;
var tip:MovieClip = new clazz();
Also, you generally want to use stage.stageWidth instead of stage.width, since the latter will return the stage bounding box width (which might not be the same as the area the swf file covers).

Related

Error joining AS2 with AS3

I have problems joining two scripts into one.
This is main part of the script: AS3.
And this is already joined script.
And here is part of the code that I need to import (AS2) :
stop();
var banners:Array = new Array();
var imagePaths:Array = new Array();
var links:Array = new Array();
var bodyTexts:Array = new Array();
var imageTime:Number;
var numberOfBanners:Number;
var isRandom:String;
var showHeader:String;
var bannersXML:XML = new XML();
bannersXML.ignoreWhite = true;
bannersXML.load("banners.xml");
bannersXML.onLoad = function(success) {
if (success) {
trace("XML LOADED");
imageTime = parseInt(this.firstChild.firstChild.firstChild)*1000;
numberOfBanners = parseInt(this.firstChild.childNodes[1].firstChild);
isRandom = this.firstChild.attributes["isRandom"];
showHeader = this.firstChild.childNodes[2].attributes["showHeader"];
var bannerSequence:Array = new Array();
if (isRandom == "true") {
//Make a random sequence
while (bannerSequence.length<numberOfBanners) {
newRandomNumber = random(numberOfBanners);
//Make sure that the random one chosen is not already chosen
for (var i = 0; i<=bannerSequence.length; i++) {
if (newRandomNumber != bannerSequence[i]) {
alreadyThere = false;
} else {
alreadyThere = true;
break;
}
}
//Add only random values that aren't in the array
if (!alreadyThere) {
bannerSequence.push(newRandomNumber);
}
}
} else {
for (var i = 0; i<numberOfBanners; i++) {
bannerSequence.push(i);
}
}
}
//Read XML in the Random Order Chosen
for (var i = 0; i<numberOfBanners; i++) {
banners.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].firstChild.firstChild.toString());
bodyTexts.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].childNodes[1].firstChild.nodeValue);
imagePaths.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].childNodes[2].firstChild.nodeValue);
links.push(this.firstChild.childNodes[2].childNodes[bannerSequence[i]].childNodes[3].firstChild.nodeValue);
}
play();
};
//Start the image counter at 0
var imageCounter = 0;
I get erorr in this part of the code
function doRandArray(a:Array):Array {//make random array
var nLen:Number = a.length;
var aRand:Array = a.slice();
var nRand:Number;
var oTemp:Object;
for (var i:Number = 0; i < nLen; i++) {
oTemp = aRand[i];
nRand = i + (random(nLen – i));
aRand[i] = aRand[nRand];
aRand[nRand] = oTemp;
}
return aRand;
}
When I run it, I get an error in this place:
nRand = i + (random(nLen – i));
Scene 1, Layer 'Layer 1', Frame 1, Line 265 1084: Syntax error: expecting rightparen before i.
as2 random(random(nLen – i)); is generate 0,1,...nLen-i-1. not floating only int value.
correct as3 code is int(Math.random()*(nLen-i)); or Math.floor(Math.random()*(nLen-i));
as2: random()
as3: Math.random()
In ActionScript 3 the random function is a little bit different from what it was in as2 code, just change the offending line to:
nRand = i + Math.random()*(nLen-1);
This should fix all errors and work just the same.
EDIT: as #bitmapdata.com indicated, for this to run the same as in as2 the random value must be truncated (stripped of its decimal values). Besides the couple of possibilities he suggested, I would personally just change nRand's type to uint on declaration:
var nRand:uint;
You can also change the iterator type to var i:uint. Less memory usage is always good ;)

AS3: Casting to Vector

I am trying to create a vector from unknown class, but it fails, any ideas about how to do it?
This is what i tried:
var vector:Vector = new Vector(); // throw exception
function base():void{
var vector:Vector.<String> = createVector(String);// throw classCastException
}
function createVector(cls:Class):*{
var array:Array = new Array();
for(var i:int = 0; i < 10; i++){
var element:cls = new cls();
array.push(element);
}
return Vector(array);
}
Vector is expecting a parameter type so you can't do this like you want, but using getQualifiedClassName to get class info you can construct a string that will enable you to call the Vector. constructor using getDefinitionByName :
Ex.
// get class parameter name
var className:String=getQualifiedClassName(String);
// get the Vector class object for the given class
var o:Object=getDefinitionByName("__AS3__.vec::Vector<"+className+">");
// call the constructor
var v:*=o.prototype.constructor(["hello", "world"]);
So your function can be written as:
public function createVector(cls:Class):*{
var cn:String = getQualifiedClassName(cls);
var o:Object = getDefinitionByName("__AS3__.vec::Vector.<"+cn+">");
var array:Array = [];
for(var i:int = 0; i < 10; i++){
var element:* = new cls();
array.push(element);
}
return o.prototype.constructor(array);
}
live example at wonderfl:
http://wonderfl.net/c/pkjs
Based on #Patrick answer I found a working solution.
Check it out:
function createVector(cls:Class):*{
var className:String = getQualifiedClassName(cls);
var vectorClass:Class = getDefinitionByName("__AS3__.vec::Vector.<"+className+">") as Class;
var vector:* = new vectorClass(10);
for(var i:int = 0; i < 10; i++){
var element:MyClass = new cls(); // may be Object or Object extends cls
vector[i] = element;
}
return vector;
}

I cant remove child of this movie clip upon clicking the back button to go function goHomePage (evt:Event):void{

Help. I need to remove the newContainer(this is a movie clip) after clicking the back button to go back to homepage.
But it just loads the homepage and the newContainer is still there. :( where did i go wrong?
import flash.events.MouseEvent;
import flash.events.Event;
import fl.motion.MotionEvent;
import flash.net.URLVariables;
import flash.display.MovieClip;
import flashx.textLayout.elements.Configuration;
var ctr:int = 0;
var now:Date = new Date();
var myurl:String = "http://localhost:8888/eventspictures/getdata.php";
var scriptLoader:URLLoader = new URLLoader();
var scriptRequest:URLRequest = new URLRequest();
var newContainer:MovieClip;
scriptRequest.url = myurl + "?ck=" + now.getTime();
scriptLoader.addEventListener(Event.COMPLETE, handleLoadSuccess);
scriptLoader.addEventListener(IOErrorEvent.IO_ERROR, handleError);
scriptRequest.method = URLRequestMethod.POST;
scriptLoader.load(scriptRequest);
function handleLoadSuccess(evt:Event):void
{
for (var j:Number = 0; j <4; j++)
{
var newContainer:MovieClip = new con();
newContainer.name = String(ctr);
newContainer.y = j*80 +65;
newContainer.x= 16;
stage.addChild(newContainer);
var variables:URLVariables = new URLVariables(evt.target.data);
trace(variables.output);
var parse:String = variables.output;
var parsed:Array = parse.split("<|>");
var tab:String = ' ';
var eventname:String = '';
var date:String='';
var slotsleft:String='';
// different variable names to assign to different column names(etc; eventname, date, slotsleft)
// loop through.. start from O
for (var i:Number = 0; i<parsed.length-1; i++)
{
trace(parsed[i]);
var item:String = parsed[i];
var itemarray:Array = item.split(",");
eventname += itemarray[2] + tab + "<br>";
date += itemarray[3] + tab;
slotsleft += itemarray[4] + tab;
trace(eventname);
newContainer.eventname_txt.htmlText = eventname;
newContainer.date_txt.htmlText= date;
newContainer.slotsleft_txt.htmlText=slotsleft;
}
}
//slotsleft_txt.x = 270;
}
function handleError(evt:IOErrorEvent):void
{
}
backbutton_mc.addEventListener(MouseEvent.CLICK, goHomePage);
function goHomePage (evt:Event):void{
gotoAndPlay("dashboard");
removeChild(newContainer);
}
stop();
In your function handleLoadSuccess() you have a loop that creates 4 MovieClip's and adds them to the stage.
But in your goHomePage() function you only try to remove one object from the stage. It turns out this object is probably null in your example (trying to remove an object that is null should generate an error if you are using the debug Flash player).
The reason it is probably null is because you have defined two variables named newContainer in your code: one is declared at the beginning of the script, and the second one inside the function handleLoadSuccess() (because you are using the keyword var on each line).
The variable created inside the function only exists while that function is executing. The variable created outside the function never seems to receive a value.
Two approaches you can use:
Keep track of the things you add to the stage, by putting them in an Array:
Replace the newContainer variable that is outside the function with an Array called containers:
var containers:Array = [];
In the function handleLoadSuccess(), when you add each MovieClip to the stage, also add them to the containers array:
stage.addChild(newContainer);
containers.push(newContainer);
Finally in the function goHomePage() iterate over the containers array to remove each MovieClip:
for (var j:int = 0; j < containers.length; j++)
{
stage.removeChild( containers[j] );
}
// reset the containers array so it's empty for the next time
// and to remove the references to the MovieClips (to prevent a memory leak)
containers=[];
Blindly remove everything from the stage
If this is accetpable, it is much easier. Just iterate backwards over the children of the stage in your goHomePage() function:
for (var j:int = stage.numChildren; j >= 1; j--)
{
stage.removeChildAt(j - 1);
}

AS3 removing dynamically created child movieclips

I'm fairly new to AS3. Anyways, I'm try to remove a dynamically created child movieclip when clicked on. When a dirt block is clicked on, which is a child movieclip of 'world' I want to remove it.
I've tried various ways of removing it using removeChild. I've also tried moving the function inside/outside of the for loop that creates the movieclips.
var blockCount:Number = 0;
var blockArray:Array = [];
var world:MovieClip = new World();
world.x = 50;
world.y = 50;
world.name = "world";
addChild(world);
for(var i:Number=1;i<=100;i++){
blockCount++;
var tempGrassBlock:MovieClip = new GrassBlock();
tempGrassBlock.x = i*16;
tempGrassBlock.y = 256;
tempGrassBlock.name = "b"+blockCount;
world.addChild(tempGrassBlock);
tempGrassBlock.addEventListener(MouseEvent.CLICK, removeBlock);
function removeBlock(event:Event){
world.removeChild(getChildByName(event.target.name));
}
}
Thanks for the help.
Try this
function removeBlock(event:Event){
world.removeChild(event.currentTarget as DisplayObject);
}
No function definition should be inside a for. I changed that in your code and rewrited a little below:
var blockCount:Number = 0;
var blockArray:Array = [];
var world:MovieClip = new World();
world.x = 50;
world.y = 50;
world.name = "world";
addChild(world);
for(var i:Number=1;i<=100;i++){
blockCount++;
var tempGrassBlock:MovieClip = new GrassBlock();
tempGrassBlock.x = i*16;
tempGrassBlock.y = 256;
tempGrassBlock.name = "b"+blockCount;
world.addChild(tempGrassBlock);
tempGrassBlock.addEventListener(MouseEvent.CLICK, removeBlock);
}
function removeBlock(event:MouseEvent){
trace("Is click really working? This target name is " + event.currentTarget.name);
world.removeChild(event.currentTarget));
}

Dynamic vars MovieClips in AS3

Hello I'm trying to do this (in as2 this worked but not in as3) I looked on google for 3 hours, but still don't found a solution (thans for your help) :
import flash.display.MovieClip;
var mcContainer:MovieClip = new MovieClip();
var mcImage0:MovieClip = new MovieClip();
var mcImage1:MovieClip = new MovieClip();
var mcImage2:MovieClip = new MovieClip();
var mcImage3:MovieClip = new MovieClip();
mcImage0.name = "Boy";
mcImage1.name = "Girl";
mcImage2.name = "Woman";
mcImage3.name = "Man";
var ArrayNamesOfMC:Array = new Array();
var i:int = 4;
while(i--) {
ArrayNamesOfMC.push(["mcImage"+i].name);
}
This donsn't work :
ArrayNamesOfMC.push(["mcImage"+i].name);
This is the simple answer to your question:
var mcImage0:MovieClip = new MovieClip();
var mcImage1:MovieClip = new MovieClip();
var mcImage2:MovieClip = new MovieClip();
var mcImage3:MovieClip = new MovieClip();
mcImage0.name = "Boy";
mcImage1.name = "Girl";
mcImage2.name = "Woman";
mcImage3.name = "Man";
var ArrayNamesOfMC:Array = new Array();
var i:int = 3;
while (i >= 0)
{
ArrayNamesOfMC.push(MovieClip(this["mcImage" + i]).name);
i--;
}// end while
The following may not be relevant in your case as I'm not quite sure what the purpose of your application is, but this is probably a better approach:
var sprites:Vector.<Sprite> = new Vector.<Sprite>();
var names:Vector.<String> = new <String>["Boy", "Girl", "Woman", "Man"];
for (var i:uint = 0; i < names.length; i++)
{
var sprite:Sprite = new Sprite();
sprite.name = names[i];
sprites.push(sprite);
}// end for
Disregard this if it is not applicable in your case.
this should do the trick:
var _movieClip:MovieClip = ("mcImage" + i) as MovieClip;
ArrayNamesOfMC.push(_movieClip.name);
Taurayi's answer is an interesting technique that I didn't know about.
Personally I would recommend restructuring your code to put all the movieclips in an array, like so:
var mcImages:Array = new Array();
for (var i = 0; i < 4; i++) {
mcImages.push(new MovieClip);
}
mcImages[0].name = "Boy";
trace(mcImages[0].name);
Incidentally, your while loop was constructed incorrectly. You need a condition in the parentheses and then do the decrement inside the loop. But with all your movieclips in an array then you can use this much simpler approach to loop through all of them:
for each (var mc in mcImages) {
trace(mc.name);
}