2008-10-01 5 views
0

J'ai une méthode d'assistance qui a été créée et qui permet à une classe basée sur MovieClip dans le code d'avoir le constructeur appelé. Malheureusement, la solution n'est pas complète car le rappel MovieClip onLoad() n'est jamais appelé.Comment créer dynamiquement une classe basée sur MovieClip Actionscript 2 avec

(Lien vers le Flashdevelop thread qui a créé la méthode.)

Comment la fonction suivante peut être modifiée de manière à la fois le constructeur et onLoad() est correctement appelé.

//------------------------------------------------------------------------ 
    // - 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; 
    } 

Un exemple d'une classe que je veux créer:

class Foo extends MovieClip 

Et quelques exemples de la façon dont je en créer la classe dans le code:

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

Répondre

2

Est-ce que je comprends correctement que vous voulez créer une instance d'un clip vide avec le comportement de classe attaché et sans avoir à définir un symbole de clip vide dans la bibliothèque?

Si c'est le cas, vous devez utiliser l'astuce des paquets. Ceci est ma classe de base (appelée View) que je me sers au fil des ans et des centaines de projets:

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

Alors, tout ce que vous devez faire pour utiliser cette classe est la sous-classer:

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

Vous pouvez maintenant créer une instance de Foo comme ceci;

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

En supposant que 'ceci' soit un type de MovieClip ou View.

Si vous devez utiliser ceci avec un symbole de bibliothèque, laissez simplement le préfixe __Packages sur le membre _symbolPackage.

Hope this helps ...

+0

Merci pour la supercherie AS2! Problème différent cependant. Un MovieClip défini dans la bibliothèque est défini sur une classe. Au moment de l'exécution, je veux ajouter des instances de cette classe à la scène et être en mesure de transmettre des arguments au ctor. Ma fonction newClassMC() appelle le ctor mais onLoad() ne se produit pas. – tronster

+0

Vous ne pouvez tout simplement pas faire cela avec Movieclips sauf si vous utilisez la composition au lieu de l'héritage. – Luke

+0

Luke, je pense toujours que c'est possible en forçant un onLoad dans la chaîne proto (ou contructor); c'est juste assez compliqué pour me faire tourner la tête. Si ce n'est pas possible, j'aimerais savoir pourquoi. – tronster

1

Si vous voulez créer une instance de la classe Foo avec des paramètres supplémentaires, vous pouvez étendre la méthode créer. Dans mon œuvre, je suis en train de créer des nœuds avec objectIds:

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

La classe Node ressemble à ceci:

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; 
}} 

S'il vous plaît noter que la objectId n'est pas défini dans le constructeur privé node() mais défini dans OnInitialize().

Questions connexes