ActionScript: programmatically adding children to a `mx:ViewStack` - actionscript-3

I have a Flex mx:ViewStack that have some Flex children, but I want to add more using ActionScript.
var o:MyCanvas = new MyCanvas;
o.id = 'modRipley';
viewStack.addChild(o);
o = new MyCanvas;
o.id = 'modNewt';
viewStack.addChild(o);
o = new MyCanvas;
o.id = 'modGorman';
viewStack.addChild(o);
Stepping through, I don't see any increase to the childDescriptors member (nor the _childDescriptors) and:
viewStack.getChildByName('modNewt');
just returns null.
I am using the Flex 3.5 SDK.

Instead of assigning o.id = 'modNewt'; use o.name = 'modNewt'; and try to access child by using viewStack.getChildByName('modNewt');. It should work.

Like my comment said, using addChild is correct, but your other code isn't useful. The childDescriptors is what the Flex framework uses to construct MXML children, so it's not expected to reflect dynamic changes made in ActionScript. And getChildByName requires that a child has a name value, while you have not given them a name, you've given them an id.
Typically, if I want to add view children dynamically, I do what the MXML compiler does with MXML children: create properties that will refer to the children when I create them. For example:
public class Example extends SomeMxmlComponentWithViewStack {
public var myCanvas1:MyCanvas;
public var myCanvas2:MyCanvas;
public var myCanvas3:MyCanvas;
override protected function createChildren():void {
super.createChildren(); // creates the MXML children
viewStack.addChild(myCanvas1 = new MyCanvas());
viewStack.addChild(myCanvas2 = new MyCanvas());
viewStack.addChild(myCanvas3 = new MyCanvas());
}
}
Now from any code you can refer to myCanvas1, myCanvas2 and myCanvas3. This is essentially what the MXML compiler does for you when you declare a component in MXML and give it an id.

Related

How to reference a variable from a class to a scene in ActionScript 3.0

I am creating a platformer in flash as3 and i want to pass the var Score for my score from Scene 1 to the next. However, I realized the best way to do this was to store the score inside a class, but I am having trouble referencing the variable inside the scenes. Please help. This is the code currently inside the class
package file_as{
public class CS{
public function CS(){
public var Score:Number = 0;
}
}
}
I tried to reference the score in scene in the frame containing my code my stating
CS.Score
But that didn't work so I'm lost.
To access it by doing CS.Score you would need to make that property static.
Static vars/methods belong to the class itself (CS in this case), if not static, they belong to instances of that class (eg var csInstance:CS = new CS(); csInstance.Score = 6;)
Here is how to make it static:
package file_as{
public class CS{
public static var Score:Number = 0;
}
}
As an aside, your current class code should be throwing an error, as you can't have the public/private keywords inside a function. Also, since you defined the var inside a function (the constructor in your case) it would only be available in that function. Notice how in my example above the var definition is at the class level.
All this said, I believe that if you defined a score var on your main timeline, it should be available across different scenes.

Multiple levels

I was reading a tutorial about creating multiple levels, and the below really interested me on how i should go about this.
It may seem natural to make one class per level, with each class
extending AvoiderGame, and use events to switch between them. So, we
might have classes named AvoiderGameLevelOne, AvoiderGameLevelTwo,
etc., and let each one fire off a “NavigationEvent.NEXT_LEVEL” when
appropriate. Presumably then the document class would listen for this
event, and when it heard it, it would run “playScreen = new
AvoiderGameLevelTwo()” (or whichever level was appropriate), and pass
through all the information such as score and time to this new
playScreen instance.
I'm not entirely sure on how to go about this. I put my stage, which is an array of tiles in a class called level1, level2, etc and had it extend my main class. Just to check if everything works, I added a public static var called levelArray in my main, which is a blank array. Then in level1, I pushed my array into levelArray.
So for my level1 class
package {
public class Level1 extends Main {
public var floor1:Array = new Array();
floor1[0] = [2,1,1,1,1,1,2];
floor1[1] = [1,1,1,1,1,1,1];
floor1[2] = [1,1,1,2,1,1,1];
floor1[3] = [1,1,1,1,1,1,1];
floor1[4] = [1,1,1,2,1,1,1];
floor1[5] = [1,1,1,1,1,1,1];
floor1[6] = [2,1,1,1,1,1,2];
public function Level1() {
Main.levelArray.push(floor1);
}
}
}
Doesn't seem to be working. levelArray comes up as blank. Might be because the two classes aren't communicating with each other correctly? Any ideas if I am approaching this the correct way?
I dont know if the rest of your concept is sound, but I think the syntax is off for the part you have shown. try:
package {
public class Level1 extends Main {
public var floor1:Array = new Array( [2,1,1,1,1,1,2],
[1,1,1,1,1,1,1],
[1,1,1,2,1,1,1],
[1,1,1,1,1,1,1],
[1,1,1,2,1,1,1],
[1,1,1,1,1,1,1],
[2,1,1,1,1,1,2]
);
public function Level1() {
Main.levelArray = floor1;
}
}
}
EDIT: if the only thing distinct about each level is the array that forms the floor, you may consider the fact that you do not need a new class for each level, just a new array. you can define the arrays for each level in the class that is super to this one and then just replace them with each progression.

ActionScript:ArrayCollection declaration

I am new to ActionScript and Flex.I need to learn the application developed using Flex and ActionScript.I saw an ArrayCollection declaration :
[Bindable]
public var someThing:ArrayCollection = new ArrayCollection([[]]);
What does that declaration mean.Is it multi dimensional?What is it?
This would be an ArrayCollection which is a wrapper for an Array basically to give you sort and filter function capabilities (and other methods). The constructor optionally takes an Array as an argument, [] is a new array with no elements. [[]] is an array with one element in it that is an array with no elements in it. So this is saying make a new ArrayCollection with it's source as an array which in turn contains one element that is an empty array. Not sure why they would be doing this, but that's what it does.
To sum up, you can declare and instantiate an array in AS3 like:
var myArray:Array = [];
or
var myArray:Array = new Array();
To add since this is I believe ECMAScript specific as well you can instantiate an object similarly using {}. Such as:
var myObj:Object = {};
or
var myObj:Object = new Object();
Either of these sites is good reference material for AS3:
http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7ee5.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7ee1
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html
When I first got started with Flex (having a background in HTML/JS, C, C++, and Java) I found these videos to be really useful (if not always 100% correct/up to date, they explain the overarching concepts):
http://www.adobe.com/devnet/flex/videotraining.html

Is Windsor able to have collection of concrete class' instances registered?

If I have interface and implementing classes like
public interface IA {}
public class X : IA {}
public class Y : IA {}
then this registering is fine
var w = new WindsorContainer();
w.Register(Component.For<IA>().ImplementedBy<X>());
w.Register(Component.For<IA>().ImplementedBy<Y>());
same as
var w = new WindsorContainer();
w.Register(Component.For<IA>().Instance(new X()));
w.Register(Component.For<IA>().Instance(new Y()));
But if I try to register concrete classes as
var w = new WindsorContainer();
var x1 = new X();
var x2 = new X();
w.Register(Component.For<X>().Instance(x1));
w.Register(Component.For<X>().Instance(x2));
it throws an exception: Castle.MicroKernel.ComponentRegistrationException : Component X could not be registered. There is already a component with that name. Did you want to modify the existing component instead? If not, make sure you specify a unique name.
If it is intended limitation - why? Is there any way to achieve collection resolve without adding interface that is not always necessary?
Did you want to modify the existing component instead? If not, make
sure you specify a unique name.
Component.For<X>().Instance(x1).Named("x1")

AS3 - How to assign names or tags to loader?

I have a list of images that i’ve loaded with the Loader class, but I’m having a tough time assigning them unique names.
I need unique names because I want to remove certain images after a while.
Is there a way to assign loaders a name or some unique tag so i can remove them later? thanks.
Here's part of my code
for (var i = startnum; i < endnum; i++){
var thumb = panels[i].#THUMB;
var thumb_loader = new Loader();
thumb_loader.load(new URLRequest(thumb));
thumb_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, thumbLoaded);
thumb_loader.name = i;
thumb_loader.x = (thumb_width + 20)*i;
}
I tried to use getChildByName in another function..
var myLoader:Loader = getChildByName( "1" ) as Loader;
myLoader.unload();
But it's giving me
Error #1009: Cannot access a property or method of a null object reference.
I tried to put thumb_loader as global variable, and do this
var myLoader:Loader = thumb_loader.getChildByName( "1" ) as Loader;
But it's still not working.
Thanks.
All display objects in ActionScript 3 have a name property. Whenever you create a Loader object you can assign a name to it like so:
var myLoader:Loader = new Loader();
myLoader.name = "myUniqueName";
myLoader.load( .... );
addChild( myLoader );
If you'd like to refer to the loader by the name you gave it, use the getChildByName() method.
var myLoader:Loader = getChildByName( "myUniqueName" ) as Loader;
myLoader.unload();
Please be mindful that getChildByName() will only work after you've added the Loader(s) to the display list using addChild(). Otherwise, you'll have to create something to store the references to the Loader objects in, such as an Array and refer to the loaders via that Array. For example, outside your loop you could create an Array named loadersArr. In your loop you would do:
loadersArr["uniqueName"] = thumb_loader;
Then you can refer to your loaders with your unique name through the loadersArr Array.
var loaderToUnload:Loader = loadersArr["uniqueName"];
loaderToUnload.unload();
Without seeing more of your code, its difficult to understand the scope in which this code resides and where any other code that may try to reference these Loaders resides.
Not sure I 100% understand your problem, but why not put them in an object map rather than a list and generate unique names for them if you don't have them...
var img:Image;
var img_map:Object = new Object();
var last_added:int = 0;
for each (img in yourListOfImages)
{
img_map["img_"+last_added] = img;
last_added++;
}
Depending on your environment (Flex or Flash) you can use a UID generator instead of my simplistic unique names above.
package
{
import flash.display.Loader;
public dynamic class DynamicLoader extends Loader
{
public function DynamicLoader()
{
super();
}
}
}
I believe the Loader class is a sealed class so you would want to create this class and use it instead of the normal Loader class to give it any attribute you want. I also believe that without using this DynamicLoader instead of the normal Loader, the Loader class does have the name property available to it.