I notice in older version of flash you can create an instance of a dynamic class. I am creating a game that will have many different classes that can be displayed on the stage but can very from time to time. How would I go about calling them dynamically. for example
var newObject = new ["DynamicObject"]();
??
Is this possible in As3 ??
I think there are 2 ways you can do that:
1.Using ApplicationDomain.getDefinition('DynamicTemplate')
something like:
var DynamicClass:Class = this.loaderInfo.applicationDomain.getDefinition('DynamicTemplate') as Class;
addChild(new DynamicClass);
You would need to do this when you file has INITialized.
2.Using getDefinitionByName() :
var DynamicClass:Class = flash.utils.getDefinitionByName('DynamicTemplate') as Class;
addChild(new DynamicClass);
If you need a way to get Class names to create new instances of objects, you could use describeType() or go through the instance's constructor, but I reckon you would know your classes anyway.
var TemplateObj:Class = flash.utils.getDefinitionByName(describeType(yourIntance).@name) as Class;
var newObj = new TemplateObj();
var newObj2 = new yourIntance.constructor();
Hope this help,
George
Occasionally, I still make calls along the lines of:
parent["MovieClipName"].someMethod();
from time to time. So I imagine your code above will work.
However, whenever I find myself using that syntax, it usually means I need to re-think my approach and use a better, more object-oriented solution.
So I would suggest that maybe what you really need to do is re-think the factors that are leading you to attempt to use the solution above. Chances are you can reach the same goal in a more object-oriented way.
Perhaps by using inheritance?
Could all of your objects extend from some common parent Object?
Perhaps by using an interface?
If it doesn't make sense for your objects to share the same parent, maybe they all can agree to share some key functions?
Maybe code along the lines of:
var tank:Enemy = new Tank();
var soldier:Enemy = new Soldier();
soldier.attack(target);
tank.attack(target);
Wnere the tank
and soldier
classes both extend from (or implement) Enemy
like this
public class Tank extends Enemy
or like this
public class Tank implements Enemy
and the Enemy class/interface contains the attack
method
Interfaces is good. I am using an array that maps out how the bricks will be put down on the stage
mapArry = [
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
];
1 specifies brick type Number 1. but what if the next map has brick type 2 or 3
mapArry = [
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
[[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
[[2],[2],[2],[2],[2],[2],[2],[2],[2],[2]],
];
Again, I loop through the array, getting each brick. how would I use interfaces to supply the given brick ?.
The only answer I could think of is the create a brickManager class. a class that identifies each type of brick and retrieves them. But I am trying to be more efficient. I would like to know if there is a better way.
Only thing i could think of is to use dynamic initiations. I didnt know that approach went against oop.
var newVar = new ["brick"+i]();
Yes, like I said, to answer your original question, what you have above will work in AS3 as it did in older versions of AS. So if it's not a big deal, you can go with it.
Overall, I wouldn't say dynamic initialization goes against OOP, per se. However, it just feels a little like a hack. Everytime I start to use something like that, I almost always find a design change that cleanly fixes the problem.
Of course it's hard to spot that change without knowing a LOT about your application. To take a stab at it:
Do you even need different classes for each brick?
Could you just set some property that ultimately changes it's behavior (like this.strength = 2)?
Then, while iterating through the array you do something like
for(var brickType:int in brickArray) {
addBrickToScreenOrWhatever( new Brick(brickType) );
}
Where the constructor Brick(int)
creates a new Brick
with a strength equal to that of the parameter.
I think I am going to go with george's solution. Except I am having a little issue with it. I was trying to do the second example. my code is below. When I call the class directly it works, but when i call by definition. doesnt work. any solution
package com.objects {
import flash.display.Sprite;
import flash.events.*;
import flash.display.Stage;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.AntiAliasType;
import flash.utils.*;
public class Engine extends Sprite {
private var pad:Paddle;
private var sRef:Stage;
private var ball:Ball;
private var bricks:BrickMap;
private var brickHolder:Array;
public var numberOfBricks:Number = 0;
public var scoreBoard:TextField;
public var score:Number = 0;
private var level = 1;
private var ready:Ready;
public function Engine(stageRef:Stage):void
{
addHud();
brickHolder = new Array();
sRef = stageRef;
pad = new Paddle();
pad.x = sRef.stageWidth/2;
pad.y = 550;
ball = new Ball();
ready = new Ready();
ready.x = sRef.stageWidth/2;
ready.y = sRef.stageHeight/2;
ready.addEventListener(MouseEvent.CLICK,gameStart);
addChild(ready);
bricks = new BrickMap();
generateMap();
}
private function generateMap():void
{
var mapW:Number = bricks.mapArry[0].length;
var mapH:Number = bricks.mapArry.length;
for(var y = 0; y < mapH; y++)
{
brickHolder[y] = new Array();
for(var x = 0; x < mapW; x++)
{
var classRef = getDefinitionByName('Brick2') as Class;
var brick:Brick2 = Brick2(new classRef());
brick.name = x+""+y;
brick.getBall(ball);
brick.getEngine(this);
brick.x = x * brick.bWidth + brick.bWidth;
brick.y = y * brick.bHeight + 100;
numberOfBricks += 1;
addChild(brick);
}
}
}//End Generate Map
}
}
I edited the above to
var classRef = getDefinitionByName('Brick2') as Class;
var brick:Brick2 = Brick2(new classRef());
also change import to
import flash.utils.*;
You can simple if you want to do it for example an editor for a game:
selectItem(e.target);
private function selectItem(whatItem:Object):void
{
var TemplateObj:Class = getDefinitionByName(getQualifiedClassName(whatItem)) as Class;
var newItem:* = new TemplateObj();