Macromedia Flash ActionScript (Frame 1)

The ActionScript used in this tutorial draws on techniques you have seen in earlier chapters. The trickiest part is assigning the event handlers for each MovieClip. Clearly you don't want to write an onPress and onRelease event handler for each MovieClip. Instead, you will use a great looping technique.

The entire Flash ActionScript will be placed on the Actions layer in Frame 1. The ActionScript has been separated into a series of functions to help you follow the flow. The functions are not split, and each step will describe the activity within the function. If certain processes need to be explained within a function, they will be explained in ActionScript comments.

  1. Place your timeline cursor on the Actions layer at Frame 1.

  2. Include the NetDebug Class file so you can monitor activity using the NetConnection Debugger:

    #include "" 
  3. Instantiate the NetConnection object to the local variable myConnection_nc. The connect() method will be called when the user presses the Login button. The ConnectionLight is connected at this point to monitor the connection state. Add the following ActionScript:

    myConnection_nc = new NetConnection(); 
  4. Define the appLogin method that will be invoked when the user clicks the Login button. This method will invoke the NetConnection connect() method. When the server responds, it will trigger the connection of the SharedObjects and UI comoponents. Add the ActionScript:

    appLogin = function () {
             myConnection_nc.connect("rtmp://localhost/makingFaces/myInstance", login_txt.
  5. Create a generic onStatus handler to receive messages from the server. This function will monitor for the NetConnection Success code. When it is received, the function knows the server has received the connection request and has invoked the Client object. In other words, it is ready to go. When the function receives the Success code, three functions will be invoked. Add the following ActionScript:

    traceStatus_template = function (info) {
             trace("Level: "+info.level+"   Code: "+info.code);
             if (info.code == "NetConnection.Connect.Success") {
                      UIComponents_init();  // Connect the UI Components
                      SharedObject_init();  // Connect and setup the SharedObject
                      clip_init(); // initialize the MovieClip events
  6. Overwrite the onStatus prototype for NetConnection and SharedObject with your generic handler traceStatus_template:

    NetConnection.prototype.onStatus = traceStatus_template;
    SharedObject.prototype.onStatus = traceStatus_template;

    Next, you must create the three functions that the onStatus handler calls when the server responds with a successful connection code.

  7. The UIComponents_init() function connects each UI component you are using once the connection has been accepted. Use this code:

    UIComponents_init = function () {
  8. Add the SharedObject_init() function to establish and connect the SharedObject:

    SharedObject_init = function () {
    = SharedObject.getRemote("kookie", myConnection_nc.uri, false);
    = function(info) {
                      for (row in info) {
                               trace("** sync["+row+"]: "+info[row].name+"CODE: "+info[row].
                               trace("** Value: "[info[0].name].x);
                               if (info[row].code != "success") {
                                        var objID =[info[row].name].id;
                                        var newX =[info[row].name].x;
                                        var newY =[info[row].name].y;
                                        this[clip_array[objID]]._x = newX;
    					    this[clip_array[objID]]._y = newY;
                                        this[clip_array[objID]].swapdepths = 0;

    The movie uses SharedObject_init() to move MovieClip objects on your stage when someone else moves it. The onSync handler embedded within this function monitors for a sync code value that is not Success. A Success message is received only when the SharedObject change was made locally. The setProperty methods change the x and y position of the MovieClip on the remote players.

    The onSync code is expanded so you can track what is going on. If you are confused why there is a loop in the onSync handler, remember that an array of objects is always returned to onSync. This is a different type of object than the information objects received by the onStatus handler. The loop will step through each array element in the info object, and check the info.code value for Success. Remember that when a client connects to a SharedObject, it will receive a series of change codes to synchronize it with the data in the SharedObject. Essentially, this loop will reposition every object that has been changed prior to it connecting.

    Within the loop, following the trace actions, the value of the properties, objID, x and y are transferred to a local function variable to make the code easy to follow. Then, using the objID value (which contains the array position of the MovieClip being affected) the name of the MovieClip is used to change the x and y position of the object. This will become clearer in the next step of the tutorial. It is this script that will change the position of the MovieClips on remote computers. Using the swapDepths property, the MovieClip will be positioned in front of all other MovieClips on the main Flash stage.

    Figure 17.5, shows the trace output of a client that is connecting to a session that has already moved pieces around. The figure's output is showing an initial synchronization of six objects and an additional two moves of the mouth1_mc.

    Figure 17.5. The Flash Output window displaying a synchronization event when a client connects to a pre-existing session.


  9. The clip_init() script will make it easy for you to assign event scripts to all the MovieClip face pieces you created. When invoked, this handy script defines an array (clip_array) that contains the instance names of each MovieClip (face part) you created. If you used different MovieClip names, the array values will have to be changed to match. The array will then be looped through and assigned two events and a new property that will identify it in the SharedObject. Add the code:

    //   This function will loop through an array of MovieClip names,
    //   and dynamically overwrite the onPress and onMouseUp events.
    //   It will also set an internal ID number used in the SharedObject
    clip_init = function () {
             /* Define the names of MovieClips */
             clip_array = new Array("eye1_mc", "eye2_mc ", "eye3_mc ", "eye4_mc ", "eye5_mc ",
    graphics/ccc.gif "eye6_mc ", "eye7_mc ", "nose1_mc ", "nose2_mc ", "mouth1_mc ", "mouth2_mc ", "mouth4_mc 
    graphics/ccc.gif", "mouth3_mc ", "nose4_mc ", "eye8_mc ", "eye9_mc ", "brow_mc ");
             /* set the length of the array to a local var */
             var clip_array_LEN = clip_array.length;
             /* loop through the array of names and set each onPress & onMouseUp */
             for (i=0; i<clip_array_LEN; i++) {
                      var mcName = clip_array[i];
                      this[mcName].onPress = MCPress;  // set the onPress event
                      this[mcName].onMouseUp = MCRelease;   // set the onMouseUp event
             this[mcName].id = i; // set an ID number to identify the clip}

    You may notice that you've assigned the onPress and the onMouseUp events to variables. To keep the code clean and understandable, these functions are defined outside of this process. The actual functions are listed in the next step. You will also notice the length of the array was transferred into a local variable (clip_array_LEN). You could place the .length method directly in the for loop; however, you will take a performance (speed) hit with that approach. Assigning it outside will increase the speed of the operation.

    When you use the Flash MX debugger, you can look at the clip_array you created (see Figure 17.6). To enable the debugger, you must have the debugger open and use the Debug Movie command (Ctrl+Shift+Enter or Control, Debug Movie).

    Figure 17.6. The Flash MX debugger displays the array object as a tree that reveals the array position and the value.


    The final two functions define the MovieClip events you assigned to the onPress() and onRelease() events in the previous step.

  10. Create the onPress function inside the MCPress variable:

    // These templates are assigned  in the clip_init()
    MCPress = function () {
             this.onMouseMove = function() {
               // write the x,y position to the SharedObject when it is being moved
            [this._name] = {, x:this._x, y:this._y};

    This function will use the startDrag() method to pick up the MovieClip and track it with the mouse position. When you do this, the MovieClip arranges itself above everything using the swapDepths() method. It will also set the onMouseMove event. The onMouseMove event is invoked when the mouse is moved. When the mouse is moving, a process will write the current position of the MovieClip to the SharedObject, thus invoking the onSync handler on each connected movie. (This is where the magic happens.)

    The Structure of the SharedObject can be reviewed in the debugger (see Figure 17.7). This shows that four objects have moved, and each has three properties (x, y, and ID).

    Figure 17.7. The Flash MX debugger displays the structure of the SharedObject. This image shows four slots, each with three properties.


  11. Create the onRelease function within the MCRelease variable.

    MCRelease = function () { 
             delete this.onMouseMove};

    This function is invoked when the user releases the mouse button. It will drop the MovieClip using stopDrag(), and it will clear the onMouseMove event.

  12. Your final act will be to ensure the playhead doesn't move by adding the lines:


That's it for the Flash ActionScript. As you can see, it really is not that complex. This application is a great example of the power of the SharedObject Synchronization engine. Think of the data it is tracking. Each time a MovieClip is moved, data is essentially streamed in and out of the server. The server-side script is very straight forward. You are not calling any processes, just requesting a connection.

Server-Side ActionScript (main.asc)

The server-side code is very simple. You need to use acceptConnection and set the username in the UI component framework.

  1. Create a new folder in the FlashCom application folder called makingFaces.

  2. Create a main.asc file and add the following SSAS to it:

    application.onConnect =function(newClient,newUserName) {
             // Set the username for the UI componetns framework
             gFrameworkFC.getClientGlobals(newClient).username =newUserName;

This application does not draw on very much processing at the server. The bulk of the work is done at the Flash player.

    Part I: 10 Quick Steps for Getting Started