Make your own free website on Tripod.com

OOP for movieClip class


Create a Class inherit from MoviClip class

MagicBall=function(){
super();
}
MagicBall.prototype=new MovieClip();

The prototype:

This prototype is created by "new MovieClip()". It seems to be an instance of MovieClip Class, but it is just an object not a movieClip. We can not implement MovieClip methods here. We can not attachMovie to this prototype object. We can not set its _x, _alpha ... etc. This prototype can not loadMovie or getURL.

MagicBall.prototype.attachMovie("square","sq",2);// not work

That script wont work.

We can create custom value or object as its property.

MagicBall.prototype.myTable=[];
MagicBall.prototype.myScore=_root.attachMovie("square","sq",2); 

This will create an array and a movieClip that can be shared by all instances.

We can set default action of onEventHandler;

MagicBall.prototype.onLoad=function(){trace(this+" is loaded");}

Thus, all instance on load will trace their name out.

We can modify existing methods.

MagicBall.prototype.loadMovie=function(swfname){
    trace(swfname);
    loadMovie(swfname,this);
}

Thus, we over-ride the old function.

The most important job is to create custom methods.

MagicBall.prototype.moveRight=function(dx){this._x+=dx;}

Most of the time, we will create a function to do initiation. This method may or may not be called by constructor.

MagicBall.prototype.init=function(){
    this.createEmptyMovieClip("holder",2);


It is interesting. These methods are going to be called by the movieClip not the prototype object. Most of these methods involve movieclip methods. They can only be called by a movieClip instance not an object. Here we define them as the methods of that prototype object but in fact nothing will happens if that prototype object really calls these methods, because that prototype itself is a regular object not a movieClip.

The constructor:

Typically, the arguments portion of the constructor is empty. No parameters in the parenthesis. It should be "MagicBall()" not MagicBall(x); Except for inheritance, we never create an instance of MagicBall by "new MagicBall(args)". Most of the time, the constructor will be called automatically when movieClip is created on to the stage. We have no chance to specify any arguments to the constructor. Dont try to initiate any values by the parameters.

If I can not initiate values by parameters, how can I create instances of MagicBall with different initial speed ? Well, we can't do that through constructor. But, we will have instance name, we can set the speed of that instance by script in frame.

How do we create an instance of "that MovieClip ?" 

We create a movieClip by putting it directly on to the stage or by scripting "createEmptyMovieClip", "attachMovie", or "duplicateMovieClip". There are no other way than these. We can not create a movieClip by "new MovieClip()", or "new MagicBall()". We might register the "MagicBall" class to a movieclip symbol with export ID "black_ball" and also register it to a movieclip symbol with export ID "red_ball". How do we know which symbol should be evoke if I say "new MagicBall()". 

When a movieClip gets debut, the prototype of associated Class will be assigned as its __proto__ and then the clip will pass through the constructor.

The movieClip is not created by "new", but it still has a __constructor__ property pointing to that constructor.

It is important to know when is the constructing time - the time when it passes through the constructor. 

For a movieclip on the stage, it is immediate before the frame script of maintime line.   (instance initiation). It is after the "initclip" block (symbol initiation). For a movieClip created by attachMovie and duplicateMovieClip, it is immediately after those commands.

OK, if it is before frame script, that means we can do nothing until it is constructed ? Is there anyway we can put our hand on the execution of constructor ? No way ! Unless you make it component. Component is equipped with "component parameter". We can read those parametera  (this.variableName) during constructing but they are not passed in through arguments. There are examples in FUIComponents.

Movieclip will not pass through the constructor if it has no "export ID" or no Class is registered to that "export ID" yet. For a movieclip on the stage, the Class registration must be done before "constructing time". Chances to register Class are in the #initclip block (symbol initiation).

If we are late, can we just manually assign the prototype to that movieClip and make it pass the constructor like this ?

mc1.__proto__=MagicBall.prototype;
mc1.__constructor__=MagicBall;
mc1.__constructor__();


Yes and NO !

If we do those actions at the begining of frame script (before instance initiation), that might work. If we are late enough, some actions have been done to mc1, then passing it through constructor might suffer the risk of re-initiation process. The result might be un-predictable.

the #initclip

In Flash 5 era, I had a project about pie chart movie. I made a movieClip symbol to represent a piece of pie. In the movieClip frame 1, I define a method "drawPiece(arc, color)". I put an instance of pie piece on the stage, and in _root I say piece1.drawPiece(30,0xFF0000); 

It fails to work. Flash executes frame script of _root before frame script of movieClip. That means I called a method that has not been defined yet. I guess, many have similar frustration to know that in _root frame 1 we can not call the functions defined in movieClip.

So, I made it a movie of two frame. The definition of functions in the movieClip will be completed in frame 1 and I called that function in the _root of frame 2.

Now, Flash MX give me a script space "before frame 1", to initiate the functions written in MovieClip. They name it the #initclip block. By this, I dont need to make my movie 2 frames any more.

Lets see what is #initclip. Generally, it is for init "symbol" not "movieclip instance". 

1.
The script in #initclip block is executed only once per "symbol". If the symbol is exported to frame 1, the symbol is init in frame 1 before any frame 1 script. It does not matter whether there is any instance on the stage or not. (Note, the script outside the #initclip block will not be executed if no instance exists in frame1). 

If that symbol is not exported to frame1, then the symbol is init in the frame where the first instance of that symbol appears. 

2.
Symbol get init only once. If we create 10 instances of that symbol, the frame script outside the #initclip block will be executed 10 times. While the #initclip block is executed only once. If those instances get unload and re-load later , the frame 1 script will be executed once more. But not the script in #initclip. Symbol get init only once.

When a looping movie loops through frame 1, the frame script will be executed for each pass through. But not for #initclip;

3. 
Symbol get init at that frame before any frame script. While the frame script outside of #initclip block is executed after all the frames script in _root. Instance initiation scripts are executed from _parent to _child.

4.
If I have several symbols get debut in the frame 1, which symbol got init first ?

It depends on the number after #initclip. The numbers needs not be "unique", but the order is important.

If symbol 2 Class inherit from symbol 1 Class, then symbol 1 Class must be init before symbol 2 Class.

5.
The script in #initclip is to init symbol before frame script. It is like usual frame script but is before frame 1. We may consider it a frame script block at top layer (Layer 0) of _root. Although #initclip block is written in movieclip symbol, the timeline is _root not movieClip. 

#initclip
    attachMovie("ball","bb",2);
    this._alpha=30;
#endinitclip


When the symbol get init, _root get a movie attached. It is _root that fades _alpha to 30; 
This is completely different from the frame script outside #initclip block. For frame script, "this" means the timeline our script is in.

6.
The above example is not good.

Although in the block of #initclip we can write any action like we do in usual frame script. Typicaly we only write script that needs to inits "symbol". There is no reason to attach a movie to _root or to change the _alpha of the _root for initing the symbol. If something gets wrong, it would be difficult to remember that, some scripts hidden here might be the fault.

To init symbol, we need a Class definition, a prototype and registering this Class to our symbol. Usually #initclip includes these script only. Nothing more.

Do it without #initclip

We see many examples making Classed Movies without #initclip. Is #initclip essential ?

Lets see the sequence when movie is loaded.

#initclip - define Class and register Class
construct - movieClips passing through constructor
frame 1 - initiate _root by frame script
movieClip frame 1 - initiate movieClip instance by frame 1 script.

Variant 1: 
We make frame 1 of maintime line be blank. Everything starts from frame 2;
We define Class and register Class at frame 1 frame script.

Variant 2:
Do not put Classed Movieclip on the stage. 
Define Class and register Class at frame 1 frame script;
After that, every movieClip is created by attachMovie.
So, the construct and instance initation will be done after symbol initiation.