DekGenius.com
[ Team LiB ] Previous Section Next Section

23.5 Stage Five

The final stage in this application is to use an XML file to load initialization data. Up to this point, we have hardcoded the number of circles as well as their properties (color, radius, and velocity) into the Flash document. However, you can create an XML document from which you can load all that data at runtime so that you can make changes to the movie without having to reexport the .swf file. Here are the steps you should complete to finish the fifth stage of the application:

  1. Open a new text document and save it as circles.xml in the same directory as where you are saving your Flash documents.

  2. Add the following content to your XML document and save it:

    <collisionMovieData>
      <!-- Define the dimensions of the rectangle within which circles can move. -->
      <bounceArea width="200" height="200" />
    
      <!-- Define the circles that should be created. In this example you create four
           circles with random velocities and colors and with various radii. -->
      <circles>
        <circle radius="30" vel="random" col="random" />
        <circle radius="5" vel="random" col="random" />
        <circle radius="24" vel="random" col="random" />
        <circle radius="10" vel="random" col="random" />
      </circles>
    </collisionMovieData>
  3. Open stage4.fla and save it as stage5.fla.

  4. Modify the code on the main timeline, as shown here (changes are in bold):

    #include "DrawingMethods.as"
    #include "MovieClip.as"
    #include "TextField.as"
    #include "Table.as"
    
    function loadData (  ) { 
      var myXML = new XML(  ); 
      myXML.ignoreWhite = true; 
    
      // Load the XML data from the XML document.
      myXML.load("circles.xml"); 
      myXML.onLoad = function (  ) { 
    
        // Get the width  and height  attribute values from the <bounceArea>  element.
        var bounceAreaWidth = this.firstChild.firstChild.attributes.width; 
        var bounceAreaHeight = this.firstChild.firstChild.attributes.height; 
    
        // Create an array to hold the values for each of the circles.
        var circlesInfo = new Array(  ); 
    
        // Get the array of the <circle>  elements.
        var circlesNodes = this.firstChild.lastChild.childNodes; 
        var atr; 
    
        // Loop through all the <circle>  elements, and add the 
        // attributes  object for each to the circlesInfo  array. 
        // The properties of the attributes  object are vel , col , and dir .
        for (var i = 0; i < circlesNodes.length; i++) { 
          circlesInfo.push(circlesNodes[i].attributes); 
        } 
    
        // Call the initCircles(  ) , initButtons(  ) , and createTable(  )  functions only
        // once the data has loaded. Pass initCircles(  )  the width and height for the
        // bounce area, and also pass it the circlesInfo  array.
        _root.initCircles(bounceAreaWidth, bounceAreaHeight, circlesInfo); 
        _root.initButtons(  ); 
        _root.createTable(  ); 
      }; 
    } 
    
    // Modify initCircles(  )  to accept parameters that define the width and height 
    // of the rectangle as well as an array of circle information objects.
    function initCircles(baW, baH, circlesInfo) {
      circles = new Array(  );
      _root.createEmptyMovieClip("circleHolder", _root.getNewDepth(  ));
      var cInfo; 
    
      // Loop through all the circle information objects, and use those
      // values to create the circle component instances.
      for (var i = 0; i < circlesInfo.length; i++) { 
        cInfo = circlesInfo[i]; 
        cir = circleHolder.attachMovie("CircleSymbol", "circle" + i,  
                                        circleHolder.getNewDepth(  )); 
        cir.init(0, 0, baW, baH, cInfo.vel, cInfo.col, cInfo.radius); 
        cir.setCircleArray(circles); 
        circles.push(cir); 
      } 
      circleHolder.createEmptyMovieClip("border", circleHolder.getNewDepth(  ));
      with (circleHolder.border) {
        lineStyle(0, 0x000000, 100);
        drawRectangle(baW, baH, 0, 0, baW/2, baH/2); 
      }
      circleHolder.onEnterFrame = function (  ) {
        var vel = 5;
        switch (this.action) {
          case "up": 
            this._y -= vel;
            break;
          case "down":
            this._y += vel;
            break;
          case "left":
            this._x -= vel;
            break;
          case "right":
            this._x += vel;
            break;
          case "rotateCW":
            this._rotation += vel;
            break;
          case "rotateCCW":
            this._rotation -= vel;
            break;
          case "scaleUp":
            this._xscale += vel;
            this._yscale += vel;
            break;
          case "scaleDown":
            this._xscale -= vel;
            this._yscale -= vel;
        }
      };
    }
    
    function initButtons (  ) {
      btnNamesAr = new Array("left", "right", "up", "down", 
                             "scaleUp", "scaleDown", "rotateCW", "rotateCCW");
      for (var i = 0; i < btnNamesAr.length; i++) {
        btn = _root.attachMovie("RectangleButtonSymbol", btnNamesAr[i] + "Btn", 
                                _root.getNewDepth(  ));
        btn.init(btnNamesAr[i]);
        btn.action = btnNamesAr[i];
        btn.onPress = pressBtn;
        btn.onRelease = releaseBtn;
      }
    }
    
    
    function pressBtn (  ) {
      _root.circleHolder.action = this.action;
    }
    
    function releaseBtn (  ) {
      _root.circleHolder.action = null;
    }
    
    
    function createTable (  ) {
      tr0 = new TableRow(5, new TableColumn(5, circleHolder));
      tr1 = new TableRow(5, new TableColumn(5, leftBtn, rightBtn, upBtn, downBtn),
                            new TableColumn(5, scaleUpBtn, scaleDownBtn),
                            new TableColumn(5, rotateCWBtn, rotateCCWBtn));
      t = new Table(5, 0, 0, tr0, tr1);
    }
    
    // Call loadData(  )  instead of the other three functions. The other
    // functions are now called once the data has loaded.
    loadData(  ); 

Save the file and test it. There are really only two changes that we have made in this stage of the application. First of all, rather than hardcode the data into the Flash document, we use an XML object to load the data into the movie at runtime. You don't want to initialize the movie until after the data has loaded, so you should invoke the initCircles( ), initButtons( ), and createTable( ) functions from within the XML object's onLoad( ) method. Additionally, you want to extract values from the XML data and pass those values along to the initCircles( ) function. The bounceAreaWidth and bounceAreaHeight values are rather self-evident. The circlesInfo array, on the other hand, might not be immediately clear. You want to construct an array in which each element represents the properties (color, velocity, and radius) of the circles that are defined in the XML document. This is rather convenient because each of the <circle> elements contains an associative array with those three properties (the attributes of the XML element). So you can use the push( ) method to append the value of each <circle> element's attributes property to the circlesInfo array.

myXML.onLoad = function (  ) {
  var bounceAreaWidth = this.firstChild.firstChild.attributes.width;
  var bounceAreaHeight = this.firstChild.firstChild.attributes.height;
  var circlesInfo = new Array(  );
  var circlesNodes = this.firstChild.lastChild.childNodes;
  var atr;
  for (var i = 0; i < circlesNodes.length; i++) {
    circlesInfo.push(circlesNodes[i].attributes);
  }
  _root.initCircles(bounceAreaWidth, bounceAreaHeight, circlesInfo);
  _root.initButtons(  );
  _root.createTable(  );
};

Then you need to make a small modification to the initCircles( ) function so that it accepts and uses the parameters loaded from the XML data. Not much needs to change. The hardcoded values for each circle's color, velocity, and radius should be replaced by the values from the circlesInfo array, and the hardcoded values that previously defined the width and height of the bounce area rectangle should be replaced by the parameters baW and baH:

for (var i = 0; i < circlesInfo.length; i++) {
  cInfo = circlesInfo[i];
  cir = circleHolder.attachMovie("CircleSymbol", "circle" + i,
        circleHolder.getNewDepth(  ));
  cir.init(0, 0, baW, baH, cInfo.vel, cInfo.col, cInfo.radius);
  cir.setCircleArray(circles);
  circles.push(cir);
}
circleHolder.createEmptyMovieClip("border", circleHolder.getNewDepth(  ));
with (circleHolder.border) {
  lineStyle(0, 0x000000, 100);
  drawRectangle(baW, baH, 0, 0, baW/2, baH/2);
}
    [ Team LiB ] Previous Section Next Section