var test:*;
test = sMC // Some movieClip exported for ActionScript
var f = new test;
Sorry if the question's a bit lame, but I begin to wonder, what does this asterisk, and the snippet mean?
Answering your original question and your question asked in a comment:
An asterisk is a wildcard which means the variable will accept any type of info. Example:
var wildcard:*;
wildcard = "hello";
wildcard = 10;
wildcard = new MovieClip();
All of the above will work.
Variables should be typed as strictly as possible; by this I mean that when you want to assign a MovieClip to a variable, your variable should be typed as a MovieClip. Like so:
var mc:MovieClip = new MovieClip();
This works for anything. If you create your own class, then use that as your type for a variable that holds your class.
var thing:MyClass = new MyClass();
An error will be thrown if you try and assign an unrelated type to a variable, like so:
var thing:MovieClip = "hello";
But as long as your variable type is somewhere along the inheritance chain of what you're assigning to it, then it will work.
var thing:DisplayObject = new MovieClip();
This can be handy if you want to loop through an array containing an assortment of your own classes that extend MovieClip.
var ar:Array = [];
/**
* MyClass extends MovieClip
* MyOtherClass extends MovieClip
*/
ar.push(new MyClass());
ar.push(new MovieClip());
ar.push(new MyOtherClass());
var i:MovieClip;
for each(i in ar)
{
trace(i);
}
Overall the wildcard type is not a recommendation. At worst use Object as everything in flash extends this. One situation where a wildcard or Object can be useful is if you want to create a function that can accept any kind of data. Like so:
var myarray:Array = [];
function addToArray(data:Object):void
{
myarray[myarray.length] = data;
trace(data);
}
OR
function addToArray(data:*):void
{
myarray[myarray.length] = data;
trace(data);
}
Hope this all makes sense.
The asterisk means the variable type is undefined, or a wildcard.
Meaning you can define test as any sort of variable.
Related
Is it possible to get the child of an object with variables IN the object instance name?
location_1, location_2 are MCs containing hidden_1, hidden_2 MCs etc.
And I'd ideally like to target the hidden objects with increasing integers inside a for loop. I've removed the for loop for ease of reading in the below:
var i = 0;
var cacheNum = 0;
var locMc = this["location_"+(i+1)]; // This works
var hiddenMc = locMc.this["hidden_"+(cacheNum+1)]; // This doesn't work!
What I'd ideally like to be possible is:
var i = 1;
var cacheNum = 1;
var hiddenMc = location_i.hiddenMc_cacheNum;
Many thanks,
Nick
The syntax for object access by name is the same as array access by number:
object[value];
In the case of arrays, the value will be a number:
var myArray:Array = ["a", "b", "c"];
myArray[0]; // "a"
In case of objects, the value will be a string:
var myObject:Object = {"a": 1, "b": 2, "c": 3}
myObject["a"] // 1
When accessing variables in the current object, you must use this, as in your example. But when using different objects, you just use the bracket notation directly:
var hiddenMc = locMc["hidden_"+(cacheNum+1)];
If the object is a DisplayObjectContainer (like Sprite or MovieClip) and the value you are accessing is a child (as in your case), you can also use the getChildByName method:
var hiddenMc = locMc.getChildByName("hidden_"+(cacheNum+1));
Like any expression, you can string accesses this way:
this["location_"+(i+1)]["hidden_"+(cacheNum+1)]
But as you can see, this is not readable and very error prone. The best way would be to store those hidden MC's in an array and access them from there. It simplifies the code because you don't need to append "hidden_" when accessing them, is usually faster and will never clash with other children with similar names.
You are attempting to bypass encapsulation by allowing code to manipulate the inner workings of an object. Do that at your own peril. Instead, provide some way for the outside object to have access on a limited basis or to be able to ask the object containing those values to perform work upon them on the caller's behalf:
public class Hidden()
{
private var _hiddenValue:int = 5;
public function get hiddenValue():int
{
return _hiddenValue;
}
public function screwWithTheHiddenValue():void
{
_hiddenValue += 25;
}
}
public class Nosey()
{
var hidden:Hidden = new Hidden();
var result:int = hidden.hiddenValue;
// result should be 5
hidden.screwWithTheHiddenValue();
result = hidden.hiddenValue;
// result should now be 30;
}
I am trying to dynamically address different instances of the same movieclip by passing a string into the movieclip address, but apparently I don't know what I'm doing. I'm trying something like below:
var vsTargetName:String;
vsTargetName = "instance50";
vsTargetName + vsThumb.thumbHighlight.visible = true;
Is something like this possible? What am I doing wrong/what do I need to do to make that work?
You could use getChildByName.
For example:
var vsTargetName:String = "instance50";
//container is a parent of vsTarget
var vsTarget:MovieClip = container.getChildByName(vsTargetName);
vsTarget.thumbHighlight.visible = true;
You can interchange object notation and array notation for DisplayObjects.
So:
var vsTargetName:String = "instance50";
this["instance50"] === this.instance50 === this[vsTargetName]
Hope that helps. You can use different combinations to select what you need:
var num:String = 50;
this["instance" + num]
The code above is very useful for loops when the MovieClip names are numbered.
In AS2 you had to call the eval() to convert a string into their relative stage object. Not sure how you would do it in AS3, I'm new to it.
var myID = "someObjectID";
var myObject = eval("someParent." + myID);
myObject._visible = false;
i'm currently using a dictionary to associate a boolean to my (non-dynamic) sprites, but i would like to know if there is a smarter way of doing this? i could just use MovieClips to assign my properties instead of Sprites since MovieClips are dynamic, but i will not be using any of the MovieClip properties or functions so it comes down to a best practice issue.
basically i want to create a state boolean property on my sprites - they are either on or off so my boolean variable is called isOn.
var mySprite:Sprite = new Sprite();
var isOn:Boolean = false;
var dict:Dictionary = new Dictionar();
dict[mySprite] = isOn;
then i will poll my sprite to check its "isOn" property. if it's on, i will turn it off - or set it to false.
if (dict[mySprite] == true)
{
dict[mySprite] = false;
}
this is the first time i'm actually using dictionaries, so please correct me if i'm using it wrong. and, of course, my original question stands: is this the best way of adding a boolean property to a non-dynamic object?
Can't you just write your own Sprite that has an isOn property? That seems like a much simpler way to achieve what you want, without using a MovieClip.
isOn could be a public var or a pair of getter/setter if you want to perform some logic when reading/writting it.
public class MySprite extends Sprite {
private var _isOn:Boolean;
public function get isOn():Boolean {
return _isOn;
}
public function set isOn(v:Boolean):void {
_isOn = v;
}
}
And then:
var mySprite:MySprite = new MySprite();
mySprite.isOn = false;
// at some later point...
if (mySprite.isOn)
{
mySprite.isOn = false;
}
is it possible to obtain the instance name of a class from the class without having to manually pass the instance name as a string parameter to the class constructor?
//Create New SizeClass
var big:SizeClass = new SizeClass();
//-------------
package
{
public class SizeClass
{
public function SizeClass()
{
trace( //-- Instance Name "big" --// );
}
}
}
No, it is not possible to know anything about the containing code block during a constructor, save what you can learn from the stack trace (though that's not available except in the debugger version of Flash). Even if you had a global access point for the containing class, it still would not allow for that access.
Think of a constructor like a method call. In a line of AS, it will be called before the assignment. Eg: var a:Foo = new Foo() the Foo is created (the constructor completes), and then a is populated with whatever just happened. After that point a will remain agnostic of its context (because of encapsulation) unless it is told about it (this is even true on a DisplayObject -- try this( var mc:MovieClip = new MovieClip(); trace( mc.root ) //this will be null ).
I'm keeping this because it is useful albeit not useful to your original answer.
You can always get the name of a class with getQualifiedClassName from the flash.utils package. You can't get a DisplayObject's until well after it has been constructed, but you can simulate this by (I believe) overriding function set name( value:String ):void. If that doesn't work, then try finding it after Event.ADDED and/or Event.ADDED_TO_SAGE.
The instance name isn't very important. You'd better store references of the instances inside an array.
var sizes:Array = new Array();
var big:SizeClass = new SizeClass();
sizes.push( big );
When you want to access them, you can loop through the array.
for (var i:uint = 0; i < list.length; ++i)
{
var size:SizeClass = list[i] as SizeClass;
trace( size );
}
BTW: Instead of an instance name it is possible to add an automatic index to your class.
package
{
public class SizeClass
{
private static var global_index:int = 0;
public const INDEX:int = global_index ++;
}
}
Which you can access like this:
var big:SizeClass = new SizeClass();
trace(big.INDEX) // 0
var small:SizeClass = new SizeClass();
trace(small.INDEX)// 1
source: http://blog.stroep.nl/2010/08/auto-increment-as3-class/
I have the following function to set up cards in a game. I created one array to hold the kind of cards, and another array to hold the position of the cards.
private function setPlayerCard(cardNumber:int, cardPos:int):void{
for (var i:int = 1; i < _CardGridInstance.numChildren+1; i++) {
var _position:MovieClip = MovieClip(_CardGridInstance.getChildByName("Position_" + i));
cardPositions[i] = _position;
cardPositions[i].pos_name.text = "position" + i;
cardPositions[i].id = ["pos"+i];
}
for (var j:int = 1; j < numCards+1; j++) {
var _c:Class = getDefinitionByName("Card_" + j) as Class;
var _cardInstance:MovieClip = new _c();
cards[j] = _cardInstance;
}
cards[cardNumber].x = _CardGridInstance.x + cardPositions[cardPos].x - 1;
cards[cardNumber].y = _CardGridInstance.y + cardPositions[cardPos].y;
addChild(cards[cardNumber]);
}
So if I want to set the card number "3" in position "5" I just write:
setPlayerCard(3,5);
The problem I can see is that every time I'd like to place a card, I am creating two arrays every time. I would like to make the arrays "global" (i.e. create it in my constructor in my document class) and reuse it in the function "setPlayerCard" however I am getting errors when I try to do so.
Any suggestions?
This is a perfect case for a Singleton static class data model. You can get the instance of the Singleton from throughout the application as it is a static class, and it can contain the two arrays without duplication.
pixelbreaker has a nice basic Singleton AS3 example that you can build from.
It's a little difficult to answer accurately without knowing how you are creating the variables and what errors you're getting. Can you post the entire class and the errors?
I can, however, recommend that you do not use the Singleton pattern. This is not a perfect case for a Singleton. The Singleton pattern has no place in OOP, it's procedural programming wrapped up like OO, but that's an argument for elsewhere.
This is, though, a perfect case for a class level variables. The following is a simple example. There are a few missing variable declarations though (numCards), as I don't know where you're creating and setting them.
package{
import flash.display.Sprite;
public class CardGame extends Sprite{
private var cardPositions:Array = new Array();
private var cards:Array = new Array();
public function CardGame(){
for var i:uint = 1; i <= _CardGridInstance.numChildren; i++) {
var position:MovieClip = MovieClip(_CardGridInstance.getChildByName("Position_" + i));
cardPositions[i] = position;
cardPositions[i].pos_name.text = "position" + i;
cardPositions[i].id = ["pos"+i];
}
for(i = 1; i <= numCards; i++) {
var c:Class = getDefinitionByName("Card_" + i) as Class;
var cardInstance:MovieClip = new c();
cards[i] = cardInstance;
}
}
private function setPlayerCard(cardNumber:uint, cardPos:uint):void{
cards[cardNumber].x = _CardGridInstance.x + cardPositions[cardPos].x - 1;
cards[cardNumber].y = _CardGridInstance.y + cardPositions[cardPos].y;
addChild(cards[cardNumber]);
}
}
}
This way you only create and populate the arrays once and you can access them from anywhere within the CardGame Class. They are not global but they are within the scope of the setPlayerCard method.
You may get errors as objects might not be instantiated when the Document Class' constructor gets called, but that can be worked around.
What is the need for the variable to be public and static?
Static means that the variable is on the Class, not instances of the Class. So every "CardGame" instance will share the same static variable. I presume, because this is the Document Class, that you will not have more than one instance of it. So there is no reason for that.
The only other reason, because you declared it public, is to make the variable accessible from outside the Class through CardGame.cardPositions. This is bad practice as you shouldn't allow other objects to directly manipulate a Classes internal data. That breaks encapsulation. Since this is the Document Class and the top of the hierarchy, you should pass a copy of the data to whichever object needs it and wait for an event to retrieve the updated data. That way you can sanitise the data before using it and you're not just blindly trusting other objects to respect your data.
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
I tried using the Singleton class, but since I had to reference MovieClips that were already on the display list, I opted for a different solution from "Actionscript 3 Tip of the Day":
http://www.kirupa.com/forum/showthread.php?p=2110830#post2110830
package {
public class ClassName {
public static var myArray_1:Object = new Object;
public static var myArray_2:Object = new Object;
public function ClassName() {
//constructor
Whatever();
DoStuffWithWhatever();
}
private function Whatever() {
// put stuff into the array here
}
private function DoStuffWithWhatever():void {
// do stuff with the array values here.
}
}
}