动态对象初始化 As3

Posted

技术标签:

【中文标题】动态对象初始化 As3【英文标题】:Dynamic Object Initiation As3 【发布时间】:2011-01-02 05:43:53 【问题描述】:

我注意到在旧版本的 Flash 中,您可以创建动态类的实例。我正在创建一个游戏,它将有许多不同的类,可以在舞台上显示,但有时会非常频繁。我将如何动态调用它们。例如

var newObject = new ["DynamicObject"]();

??

这在 As3 中可能吗??

【问题讨论】:

【参考方案1】:

我认为有两种方法可以做到这一点:

1.使用ApplicationDomain.getDefinition('DynamicTemplate')

类似:

var DynamicClass:Class = this.loaderInfo.applicationDomain.getDefinition('DynamicTemplate') as Class;
addChild(new DynamicClass);

当您的文件已初始化时,您需要这样做。

2.使用getDefinitionByName():

var DynamicClass:Class = flash.utils.getDefinitionByName('DynamicTemplate') as Class;
addChild(new DynamicClass);

如果您需要一种方法来获取类名来创建对象的新实例,您可以使用describeType() 或通过实例的构造函数,但我认为您无论如何都会知道您的类。

var TemplateObj:Class = flash.utils.getDefinitionByName(describeType(yourIntance).@name) as Class;
var newObj = new TemplateObj();
var newObj2 = new yourIntance.constructor();

希望对您有所帮助, 乔治

【讨论】:

这听起来是一个非常好的解决方案。正如 gmale 所说,我什至可以将其封装到工厂中。甚至创建一个像这样的接口 var DynamicClass:IClass = flash.utils.getDefinitionByName('DynamicTemplate') as IClass;谢谢你的提示。还有一件事。我必须使用什么库。或者什么类使用这个方法。我刚刚尝试了第一个并得到一个方法是空错误。我猜第二个属于 flash flash.utils 库。谢谢!!! flash.utils.getDefinitionByName('PutAnyClassNameHere') 返回一个您强制转换为 Class 然后创建它的实例的对象。如果你得到空值,这意味着没有名称(字符串)作为参数传递给 getDefinitionByName() 的可见类。 flash.utils.* 中有很多方便的功能。 至于第二个,我对那个有问题。我把代码放进去。 虽然我已经弄清楚了。当我必须将对象转换为特定类型的类时,我不确定如何广泛使用我选择的类。是的,我所有的课程都将是子类。但是,如果我将子类转换为父类变量。我还能调用子类方法吗?我该怎么做呢。因为这是一个新问题。我可能会打开另一个帖子。 每天学习新东西——我不知道 describeType()。这完全使“is”关键字过时了。谢谢,乔治!【参考方案2】:

偶尔,我仍然会按照以下方式拨打电话:

parent["MovieClipName"].someMethod();

不时。所以我想你上面的代码会起作用。

但是,每当我发现自己使用这种语法时,这通常意味着我需要重新考虑我的方法并使用更好、更面向对象的解决方案。

因此,我建议您可能真正需要做的是重新考虑导致您尝试使用上述解决方案的因素。您有可能以更加面向对象的方式实现相同的目标。

也许通过使用继承? 您的所有对象都可以从某个公共父对象扩展而来吗?

也许通过使用接口? 如果您的对象共享同一个父对象没有意义,也许它们都可以同意共享一些关键功能?

也许代码如下:

var tank:Enemy = new Tank();
var soldier:Enemy = new Soldier();

soldier.attack(target);
tank.attack(target);

tanksoldier 类都像这样从 Enemy 扩展(或实现)

public class Tank extends Enemy

或者像这样

public class Tank implements Enemy

并且 Enemy 类/接口包含 attack 方法

【讨论】:

我明白你的意思了。我应该用那个。但是看看我的代码,我肯定没有设计成那样使用它。我正在创建一个像 BreakOut 这样的游戏。您必须用球击球的地方。我让砖类负责检测与球的碰撞,并在被击中时自行移除。在这样做之前将积分放到记分板上。我所要做的就是打电话给它。但是会有其他类继承自它。更坚固的砖块在它自己移除之前会受到更多的打击。当然我会超越这些方法。但是当需要添加它们时呢 为了让我添加这些新积木,我可以创建另一种方法来生成这些不同类型的积木以及旧积木。但这会很乏味。所以我会使用相同的方法根据数组中给出的值生成不同类型的砖块。所以说数组 4 是一个新的砖块。给定数组中的值,我将如何使用接口来提供不同类型的砖块或任何类型的砖块? 嗯,首先,我将上面的内容输入到 Flex Builder 中并编译。所以我的猜测是它会起作用。因此,您可能可以这样做。但是,我建议仔细查看您的代码,看看是否有一种干净的方法来重新设计它,这样您就不必根据数组的内容来实例化对象。您可能可以进行一些基本的高级设计更改来清理内容,因此无需这样做即可工作。或者不是......只有对你在做什么的深刻理解才能回答这个问题。如果事实证明您需要数组,那么... ...我将使用的解决方案(不知道你在做什么)正是你所建议的。根据我发送的参数或应用程序的状态,使用某种工厂方法来构建我需要的对象。例如,只要某些条件为真(如当前的砖行 如 BrickBuilder.createBrick(currentLevel);【参考方案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]],
      [[1],[1],[1],[1],[1],[1],[1],[1],[1],[1]],
      ];

1 指定编号为 1 的砖块。但是如果下一张地图的砖块类型为 2 或 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]],
      ];

再一次,我循环遍历数组,得到每一块砖。我将如何使用接口来提供给定的砖?。

我能想到的唯一答案是创建一个brickManager 类。识别每种类型的砖并检索它们的类。但我正在努力提高效率。我想知道是否有更好的方法。

我唯一能想到的就是使用动态启动。我不知道这种方法与 oop 相悖。

var newVar = new ["brick"+i]();

【讨论】:

【参考方案4】:

是的,就像我说的那样,为了回答您最初的问题,您上面的内容将在 AS3 中工作,就像在旧版本的 AS 中一样。所以如果没什么大不了的,你可以去。

总的来说,我不会说动态初始化本身就违背 OOP。但是,它只是感觉有点像黑客。每次我开始使用类似的东西时,我几乎总能找到彻底解决问题的设计更改。

当然,如果不了解您的应用程序,就很难发现这种变化。试一试:

你甚至需要为每块积木设置不同的类吗?

您能否设置一些最终改变其行为的属性(例如 this.strength = 2)?

然后,在遍历数组时,您可以执行类似的操作

for(var brickType:int in brickArray) 
    addBrickToScreenOrWhatever( new Brick(brickType) );

构造函数Brick(int) 创建一个新的Brick,其强度等于参数的强度。

【讨论】:

【参考方案5】:

我想我会采用乔治的解决方案。除了我有一个小问题。我试图做第二个例子。我的代码如下。当我直接调用该类时,它可以工作,但是当我按定义调用时。不工作。任何解决方案

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
       

我将以上内容编辑为

var classRef = getDefinitionByName('Brick2') as Class;
var brick:Brick2 = Brick2(new classRef());

还将导入更改为

import flash.utils.*;

【讨论】:

导入 flash.utils.*;让事情变得更容易 你有一个名为 Brick2 的类吗?如果是这样,你要么做 var classRef = getDefinitionByName('Brick2') as Class var brick:Brick2 = Brick2(new classRef());我不明白brick2(小写b)来自哪里?你有一个叫brick2的类吗?使用 getDefinintionByName() 的全部优势是您可以动态访问类,假设您有 20 个不同的 Brick 类,您将拥有类似:for(var i:int = 0 ; i 我要访问的类是 Brick2。我有 Brick 和 Brick2。但在这种情况下,我试图到达 Brick2。没有砖。那是一个错字。但现在我遇到了一个新错误。我更新了上面的代码。我收到此错误.... ReferenceError: 错误 #1065: 变量 Brick2 未定义。 我注意到我必须将它转换为特定的类。所以我可能不得不设置一个接口来让他们的方法正常工作。对吗?? 我想我已修复它。我没有将“Brick2”传递给参数,而是输入了完整路径。 com.objects.Brick2 !【参考方案6】:

如果你想做一个游戏的编辑器,你可以很简单:

selectItem(e.target);       

private function selectItem(whatItem:Object):void

    var TemplateObj:Class = getDefinitionByName(getQualifiedClassName(whatItem)) as Class;
    var newItem:* = new TemplateObj();

【讨论】:

以上是关于动态对象初始化 As3的主要内容,如果未能解决你的问题,请参考以下文章

在 AS3 中为游戏存储 XML 数据的最佳方式

什么是 C++ 中对象的动态初始化?

如何初始化动态对象数组

使用默认值初始化动态创建的对象 - 使用泛型和接口

对象数组

通过动态调用(获取)属性来初始化(实体)对象。实体框架,c#,ASP>NET