Как динамически создать класс на основе ActionScript 2 MovieClip с - PullRequest
1 голос
/ 01 октября 2008

У меня есть вспомогательный метод, который позволяет классу на основе MovieClip в коде и вызывать конструктор. К сожалению, решение не является полным, потому что обратный вызов MovieClip onLoad () никогда не вызывается.

(ссылка на поток Flashdevelop , который создал метод.)

Как можно изменить следующую функцию, чтобы правильно вызывать и конструктор и onLoad () .

    //------------------------------------------------------------------------
    //  - Helper to create a strongly typed class that subclasses MovieClip.
    //  - You do not use "new" when calling as it is done internally.
    //  - The syntax requires the caller to cast to the specific type since 
    //    the return type is an object. (See example below).
    //
    //  classRef, Class to create 
    //  id,       Instance name
    //  ...,      (optional) Arguments to pass to MovieClip constructor
    //  RETURNS   Reference to the created object 
    //  
    //  e.g., var f:Foo = Foo( newClassMC(Foo, "foo1") );
    //
    public function newClassMC( classRef:Function, id:String ):Object 
    {
      var mc:MovieClip = this.createEmptyMovieClip(id, this.getNextHighestDepth()); 
      mc.__proto__ = classRef.prototype; 

      if (arguments.length > 2) 
      {
        // Duplicate only the arguments to be passed to the constructor of
        // the movie clip we are constructing.
        var a:Array = new Array(arguments.length - 2);
        for (var i:Number = 2; i < arguments.length; i++)
          a[Number(i) - 2] = arguments[Number(i)];

        classRef.apply(mc, a);
      }
      else
      {
        classRef.apply(mc);
      }

      return mc; 
    }

Пример класса, который я могу захотеть создать:

class Foo extends MovieClip

И несколько примеров того, как я сейчас создал бы класс в коде:

// The way I most commonly create one:
var f:Foo = Foo( newClassMC(Foo, "foo1") );

// Another example...
var obj:Object  = newClassMC(Foo, "foo2") );
var myFoo:Foo   = Foo( obj );

Ответы [ 2 ]

3 голосов
/ 03 октября 2008

Правильно ли я понимаю, что вы хотите создать экземпляр пустого фрагмента ролика с прикрепленным поведением класса и без необходимости определять пустой символ клипа в библиотеке?

Если это так, вам нужно использовать трюк с пакетами. Это мой базовый класс (называется View), который я использовал на протяжении многих лет и в сотнях проектов:

import mx.events.EventDispatcher;

class com.tequila.common.View extends MovieClip
{
    private static var _symbolClass : Function = View;
    private static var _symbolPackage : String = "__Packages.com.tequila.common.View";

    public var dispatchEvent : Function;
    public var addEventListener : Function;
    public var removeEventListener : Function;

    private function View()
    {
        super();

        EventDispatcher.initialize( this );

        onEnterFrame = __$_init;
    }

    private function onInitialize() : Void
    {
            // called on the first frame. Event dispatchers are
            // ready and initialized at this point.
    }

    private function __$_init() : Void
    {
        delete onEnterFrame;

        onInitialize();
    }

    private static function createInstance(symbolClass, parent : View, instance : String, depth : Number, init : Object) : MovieClip
    {
        if( symbolClass._symbolPackage.indexOf("__Packages") >= 0 )
        {
            Object.registerClass(symbolClass._symbolPackage, symbolClass);
        }

        if( depth == undefined )
        {
            depth = parent.getNextHighestDepth();
        }

        if( instance == undefined )
        {
            instance = "__$_" + depth;
        }

        return( parent.attachMovie(symbolClass._symbolPackage, instance, depth, init) );
    }

    public static function create(parent : View, instance : String, depth : Number, init : Object) : View
    {
        return( View( createInstance(_symbolClass, parent, instance, depth, init) ) );
    }
}

Итак, все, что вам нужно сделать, чтобы использовать этот класс, это сделать его подклассом:

class Foo extends View
{
    private static var _symbolClass : Function = Foo;
    private static var _symbolPackage : String = "__Packages.Foo";

    private function Foo()
    {
       // constructor private
    }

    private function onInitialize() : Void
    {
            // implement this to add listeners etc.
    }

    public static function create(parent : View, instance : String, depth : Number, init : Object) : Foo
    {
        return( Foo( createInstance(_symbolClass, parent, instance, depth, init) ) );
    }
}

Теперь вы можете создать экземпляр Foo следующим образом:

var foo : Foo = Foo.create( this );

Предполагая, что 'this' - это какой-то тип MovieClip или View.

Если вам нужно использовать это с символом библиотеки, просто не указывайте префикс __Packages в элементе _symbolPackage.

Надеюсь, это поможет ...

2 голосов
/ 30 мая 2011

Если вы хотите создать экземпляр класса Foo с дополнительными параметрами, вы можете расширить метод create. В моей реализации я создаю узлы с objectIds:

var node : Node = Node.create(1,_root );

Класс Node выглядит следующим образом:

class Node extends View {

private static var _symbolClass : Function = Node;
private static var _symbolPackage : String = "Node";

private var objectId : Number;


private function Node() {
   // constructor private
   trace("node created ");
}

private function onInitialize() : Void {
    //add listeners
}

public static function create(id_:Number, parent : MovieClip,  instance : String, depth : Number, init : Object) : Node {
    var node :Node = Node( createInstance(_symbolClass, parent, instance, depth, init) )
    node.setObjectId(id_);
    return(node);
}   

//=========================== GETTERS / SETTERS
function setObjectId(id_:Number) : Void {
    objectId = id_;
}
function getObjectId() : Number {
    return objectId;
}}

Обратите внимание, что objectId не определен в приватном конструкторе Node (), но определен в onInitialize ().

...