Dynamic Object Initiation As3

2019-02-20 21:13发布

问题:

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 ??

回答1:

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



回答2:

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



回答3:

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]();


回答4:

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.



回答5:

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.*;


回答6:

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();