Динамическая инициация объекта As3 - PullRequest
0 голосов
/ 07 января 2010

Я заметил, что в более старой версии flash вы можете создать экземпляр динамического класса. Я создаю игру, в которой будет много разных классов, которые могут отображаться на сцене, но время от времени - очень. Как бы я назвал их динамически? например

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

??

Возможно ли это в As3 ??

Ответы [ 6 ]

3 голосов
/ 07 января 2010

Я думаю, что есть 2 способа сделать это:

1.Использование ApplicationDomain.getDefinition ('DynamicTemplate')

что-то вроде:

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

Это необходимо сделать, когда файл INITialized.

2.Использование getDefinitionByName ():

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

Если вам нужен способ получить имена классов для создания новых экземпляров объектов, вы можете использовать descriptionType () или пройти через конструктор экземпляра, но я считаю, что вы все равно знаете свои классы. *

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

Надеюсь, эта помощь, George

2 голосов
/ 07 января 2010

Иногда я все еще звоню по телефону:

parent["MovieClipName"].someMethod();

время от времени. Итак, я думаю, что ваш код выше будет работать.

Однако всякий раз, когда я обнаруживаю, что использую этот синтаксис, это обычно означает, что мне нужно переосмыслить свой подход и использовать лучшее, более объектно-ориентированное решение.

Поэтому я хотел бы предположить, что, возможно, вам действительно нужно переосмыслить факторы, побуждающие вас попытаться использовать вышеуказанное решение. Скорее всего, вы можете достичь той же цели более объектно-ориентированным способом.

Возможно, используя наследование? Могут ли все ваши объекты расширяться от некоторого общего родительского объекта?

Возможно, с помощью интерфейса? Если для ваших объектов не имеет смысла совместно использовать одного и того же родителя, может, они все могут согласиться разделить некоторые ключевые функции?

Может быть, код такой:

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

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

Где классы tank и soldier расширяются от (или реализуют) Enemy следующим образом

public class Tank extends Enemy

или как это

public class Tank implements Enemy

и класс / интерфейс Enemy содержит метод attack

1 голос
/ 07 января 2010

Я думаю, что собираюсь пойти с решением Джорджа. За исключением того, что у меня есть небольшая проблема с этим. Я пытался сделать второй пример. мой код ниже. Когда я вызываю класс напрямую, это работает, но когда я звоню по определению. не работает любое решение

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.*;
1 голос
/ 07 января 2010

Да, как я уже сказал, чтобы ответить на ваш первоначальный вопрос, то, что у вас есть выше, будет работать в AS3, как и в более старых версиях AS. Так что, если это не имеет большого значения, вы можете пойти с этим.

В целом, я бы не сказал, что динамическая инициализация идет против ООП как таковой. Тем не менее, это просто похоже на взломать. Каждый раз, когда я начинаю использовать что-то подобное, я почти всегда нахожу изменение дизайна, которое чисто решает проблему.

Конечно, трудно заметить это изменение, не зная МНОГО о вашем приложении. Чтобы нанести удар в этом:

Вам нужны разные классы для каждого кирпича?

Не могли бы вы просто установить какое-либо свойство, которое в конечном итоге меняет его поведение (например, this.strength = 2)?

Затем, перебирая массив, вы делаете что-то вроде

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

Где конструктор Brick(int) создает новый Brick с силой, равной силе параметра.

1 голос
/ 07 января 2010

Интерфейсы это хорошо. Я использую массив, который отображает, как кирпичи будут размещены на сцене

 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. класс, который идентифицирует каждый тип кирпича и получает их. Но я стараюсь быть более эффективным. Я хотел бы знать, есть ли лучший способ.

Единственное, о чем я мог думать, это использовать динамические инициации. Я не знал, что этот подход пошел против упс.

var newVar = new ["brick"+i]();
0 голосов
/ 04 июля 2012

Вы можете сделать это простым, например, редактором для игры:

selectItem(e.target);       

private function selectItem(whatItem:Object):void
{
    var TemplateObj:Class = getDefinitionByName(getQualifiedClassName(whatItem)) as Class;
    var newItem:* = new TemplateObj();
...