Building a Basic Menu in ActionScript 3.0 Tutorial – Part 2 – XML

A few posts ago, I showed you how to build a basic menu using an Array of button names. Now, I will demonstrate how to build the same menu, but this time use the new XML class which is based on E4X. There are many benefits of using XML in your applications. The main reason being that it allows you to update your application instantly without having to open up Flash to republish it. XML also allows your application to be easily updated from a server side page that generates XML output. This opens up the possibility of using a CMS to modify your application, thus enabling your clients to make updates on their own. Almost every project I develop uses XML.

And now for the code:

package ca.flashdev.example {		

  import flash.display.Sprite;
  import flash.display.Shape;
  import flash.events.MouseEvent;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;
  import flash.text.TextFormat;
  import flash.net.URLLoader
  import flash.net.URLRequest
  import flash.xml.XML
  import flash.events.Event;
  import flash.error.Error;

  public class BasicMenuXML extends Sprite {		

    // Create an XML list to hold the buttons.
    private var __menuList:XMLList;	 

    // External file loader.
    private var __loader:URLLoader;

    /**
     * The constructor. This method is fired
     * automatically when the class is instantiated.
     */
    public function BasicMenuXML():void {
      loadXML();
    }

    /**
     * Load the XML.
     */
    private function loadXML():void {			

      // Create a URL loader.
      __loader = new URLLoader();

      // Attach a listener to the loader.
      __loader.addEventListener(Event.COMPLETE, onXMLLoaded);

      // Load the xml file.
      __loader.load(new URLRequest("menu.xml"));
    }

    /**
     * Called when the XML has been loaded.
     * @param   event   The event that called this method.
     */
    private function onXMLLoaded(event:Event):void {

      // Put some error catching in case the XML is malformed.
      try {

        // Load the data into the XML object.
        var menuXML:XML = new XML(__loader.data);

        // Create a list of the buttons.
        __menuList = menuXML.button; 

        // Now that the XML is loaded create the menu.
        drawMenu();	

      } catch(error:Error) {

        // Display an error message.
        var errorMessage:TextField = new TextField();
        errorMessage.autoSize = TextFieldAutoSize.LEFT;
        errorMessage.textColor = 0xFF0000;
        errorMessage.text = error.message;
        addChild(errorMessage);
        return;
      }
    }

    /**
     * Draw the menu.
     */
    private function drawMenu():void {

      // This variable will hold the x position for the next button.
      var xPos:Number = 0;

      // Create a holder that will contain the menu.
      var menuHolder:Sprite = new Sprite();

      // Add the holder to the stage.
      addChild(menuHolder);			

      // Create text formatting for the text fields in the menu.
      var format:TextFormat = new TextFormat();
      format.font = "Verdana";
      format.color = 0x000000;
      format.size = 12;
      format.bold = true;

      // Loop through the list and create each button in the list.
      var count:int = 0;
      for each (p in __menuList) {

        // Create the button.
        var button:Sprite = new Sprite();
        button.name = "button"+count;

        // Disable the mouse events of objects inside the button.
        button.mouseChildren = false;

        // Make the sprite behave as a button.
        button.buttonMode = true;

        // Create the label for the down button state.
        var label:TextField = new TextField();
        label.autoSize = TextFieldAutoSize.LEFT;
        label.selectable = false;
        label.defaultTextFormat = format;
        label.text = __menuList[count].text();

        // Create a up state for the button.
        var up:Sprite = new Sprite();
        up.graphics.lineStyle(1, 0x000000);
        up.graphics.beginFill(0x00FF00);
        up.graphics.drawRect(0, 0, 100, 30);
        up.name = "up";

        // Create a over state for the button.
        var over:Sprite = new Sprite();
        over.graphics.lineStyle(1, 0x000000);
        over.graphics.beginFill(0xFFCC00);
        over.graphics.drawRect(0, 0, 100, 30);
        over.name = "over";

        // Adder the states and label to the button.
        button.addChild(up);
        button.addChild(over);
        button.addChild(label);				

        // Position the text in the center of the button.
        label.x = (button.width/2) - (label.width/2);
        label.y = (button.height/2) - (label.height/2);

        // Add mouse events to the button.
        button.addEventListener(MouseEvent.MOUSE_OVER,
                                  displayActiveState);
        button.addEventListener(MouseEvent.MOUSE_OUT,
                                  displayInactiveState);
        button.addEventListener(MouseEvent.CLICK, displayMessage);

        // Add the button to the holder.
        menuHolder.addChild(button);

        // Position the button.
        button.x = xPos;

        // Increase the x position for the next button.
        xPos += button.width + 2;

        // Hide the over state of the button.
        over.alpha = 0;

        // Increase the count.
        count++;
      }

      // Postion The Menu.
      menuHolder.x = 20;
      menuHolder.y = 20;

    }

    /**
     * Show the active state of the button.
     */
    private function displayActiveState(event:MouseEvent):void {

      // Hide the over state of the button.
      event.currentTarget.getChildByName("over").alpha = 100;
    }

    /**
     * Hide the active state of the button.
     */
    private function displayInactiveState(event:MouseEvent):void {

      // Show the over state of the button.
      event.currentTarget.getChildByName("over").alpha = 0;
    }

    /**
     * Display a message in the Output window.
     */
    private function displayMessage(event:MouseEvent):void {

      // Output the name of the clicked button.
      trace(event.currentTarget.name)
    }
  }
}

Save this file as BasicMenuXML.as in a folder structure of ca.flashdev.example.
Create a new movie and add ca.flashdev.example.BasicMenuXML to the ActionScript 3.0 Settings Document class field. Save this file as basicMenuXML.fla in the same directory as your ca folder. Publish (Ctrl+Enter) your movie and you should see the menu.

Download the source files

Tagged , , , , , ,

26 thoughts on “Building a Basic Menu in ActionScript 3.0 Tutorial – Part 2 – XML

  1. swanthon says:

    Hehe, if anyone’s trying to run this code, you’ll want to edit the import statements to:
    import flash.xml.XMLDocument;
    import flash.errors.*;
    to reflect changes to packages in ActionScript 3.0

  2. rem7 says:

    doing
    import flash.xml.XML; won’t work

    and

    import flash.xml.XMLDocument; will use the old XML from Actionscript2.0 wouldnt it?

    source:
    http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000132.html

  3. This tutorial was written for Flash 9, not Flash CS3, thus the incorrect import statements. import flash.xml.XMLDocument; is the correct statement and will use E4X. Thanks for the correction.

  4. gonzo says:

    I really new at this. Exactly what does this mean, “the ActionScript 3.0 Settings Document class field.”??

    I searched the entire menu and couldn’t find how to bring the source into Flash CS3 the correct way so that this would work. I loaded the .fla in the zip file and saw that it indeed works..but i want to do it myself.

    thanks,

  5. In Flash CS3 the Document Class field is at the bottom of the screen in the properties inspector right below the publish settings.

  6. Dion says:

    Hello, i am also really new to this.
    How can i make the buttons refer to a frame or link to another page in the website….?
    Do i have to adjust the xml file for that or something?

  7. aDOLFOrUIZ says:

    I compiled it as shown and it threw me an error..

    1120: Access of undefined property p.

    At this line

    for each (p in __menuList) {

    then went reading and found that p must be defined.. and defined as an XML var.. thus the result will be..

    …….
    var p:XML;
    for each (p in __menuList) {
    …….

    Thanks for the tutorials.

  8. peter souza says:

    im trying to make a ‘morphing button’

    i have an invisible button, and shape animated frames thay acount for the states of the button

    these codes work just fine individually, but whn they are combined like this it doesnt work properly anymore

    what am i doing wrong here

    button1.addEventListener
    (MouseEvent.MOUSE_OVER,
    function(MouseEvent)
    {(gotoAndPlay(“over”,”Scene 3″))});

    button1.addEventListener
    (MouseEvent.MOUSE_OUT,
    function(MouseEvent)
    {(gotoAndPlay(“out”,”Scene 3″))});

    button1.addEventListener
    (MouseEvent.MOUSE_UP,
    function(MouseEvent)
    {(gotoAndStop(2))});

  9. Tony says:

    Hi,

    Thanks for the tutorial. I built my AS3 code taking an xml file, parsing that into multiple arrays, then used those arrays to create buttons and populate the text fields of those buttons. Now that I see this tutorial, maybe I should just go straight from xml – buttons. Any reason not to?

  10. Tony says:

    here is my xml to array to movie clip code, but I’m having a hard time making my movie clips respond like buttons:

    var xml:XML = new XML();
    var loader:URLLoader = new URLLoader();
    loader.load(new URLRequest(“fsproconfig2.xml”));
    loader.addEventListener(
    Event.COMPLETE,
    function(evt:Event):void {
    xml = XML(evt.target.data);
    var newCircleX:Number;
    var newCircleY:Number;

    var num:Number = xml.fsproevent.length();
    var fsproeventname:Array = new Array();
    var fsproeventdate:Array = new Array();
    var fsproeventpackage:Array = new Array();
    var fsproeventID:Array = new Array();
    var fsproeventlocation:Array = new Array();
    var fsproeventtheme:Array = new Array();

    newCircleX = 200;
    newCircleY = 400;

    for (var i:Number = 0; i

  11. Hi Tony,

    It looks like there must be a max amount of lines or characters for a comment as your last chunk of code got cut off. With E4X I find I am using arrays much less and XML much more. I would say that there is no need to parse XML anymore.

    Maybe you can email me your code and I will add it to your comment above if WordPress lets me.

    Fraser ;)

  12. Norley Tucker says:

    Many thanks for this and the previous tutorial, nice and clear and finally helped me to get my dynamic buttons working, cheers :)

  13. Mark says:

    I have a question. I have been doing Flash 2.0 for years, and the switch has been pretty hard. A simple action for an object to move to the right won’t even work. I’ve switch all the _x’s to x’s, and all _root’s to root’s. Heres my code:
    First Frame:
    x += 15;

    Second Frame:
    gotoAndPlay(1);

    What’s wrong?

  14. Mark says:

    *I mean the switch to 3.0, in CS3*

  15. Mark says:

    Also, I can’t figure out a simple command for the 2.0 code:

    on(release){
    _root.gotoAndStop(2);
    }

    How do I do so in 3.0?

  16. Hi Mark,

    I just tested it out and it works fine. Make sure you give your movieClip an instance name (ie. test_mc) and then just use test_mc.x += 15.

    Watch out for root. I personally recommend you never use root because it will restrict the flexibility of your movie. Say you build an animation and use root to control its playback. If you ever want to use that animation inside another Flash project, chances are it will not work like you expect it to. I recommend you stick to using parent, or passing a reference movieClip into your code. Also, I am pretty sure root’s reference has changed in AS3. I believe it no longer refers to the Stage as it did in AS2.

    You can no longer use movieClip handlers in ActionScript 3. So, all of the on(release) crap is gone, thank God. You will have to start coding your projects using instance names for your movieClips like I mentioned above. Check out some of the tutorials on this site and others to learn about using Events.

    Hope this helps.

    Fraser ;)

  17. technoman says:

    Thanx for this great tutorial.
    I have just finished the book essential actionscript 3.0
    by colin moock and your tutorials are helping me a lot.
    I am also trying to convert the basic bookselectionsytem
    (example from the book flash application design solutions by ka wai cheung and craig bryant, chapter 3)
    from as2 to as3, but i am stuck with the code on the .fla
    Is there anybody who has tried this or who knows where to
    find a simular example?

  18. qpixo says:

    I follow this tutorial but want to add another feature. Had a hard time to figure this in AS3.
    How to make a mouse selected, initialize to “button0″ when the user click to each other button. this color will be appear in others?

  19. psio says:

    Fraser,

    First off thanks for this great tutorial, but I’m running into several problems/errors. Here is the list of errors in the compiler…

    1180: Call to a possibly undefined method addChild.
    1180: Call to a possibly undefined method addChild.
    1172: Definition flash.error:Error could not be found.
    5000: The class ‘code.actionscript.MenuXML’ must subclass ‘flash.display.MovieClip’ since it is linked to a library symbol of that type.

    The first two addChild errors refer to the XML loading class. The import.error.Error isn’t right for some reason in the third error. And the last one is just weird to be honost, it refers to the classification next to package path.goes.here{

    Thanks for any help!

  20. psio says:

    OK, so I’ve fixed all of the errors except the remaining two, which have me completely stumped!

    1180: Call to a possibly undefined method addChild.
    This is for the part after this code…

    var menuHolder:Sprite = new Sprite();
    addChild(menuHolder);

    5000: The class ‘code.MenuXML’ must subclass ‘flash.display.MovieClip’ since it is linked to a library symbol of that type.

    This is a result of line 1, I’m just trying to show the path… help?

  21. worked says:

    Thanks for the tut! I have one question, how would I animate this menu? If I wanted each button to animate on the screen to specific location at runtime, how would I do that? Do I need to store the XML into an array first?

  22. Thank you for the tutorial, it was very helpful for me.
    After changing the imports u have listed in the code to these imports:
    import flash.xml.XMLDocument;
    import flash.errors.*;
    I had also the cpile error in this part
    [ for each (p in __menuList) { ]
    p seems to be undefined
    I have fixed the errors and I succeeded to get the code running.Now apllication can be instantly updated without having to open up Flash to republish it.

  23. manny says:

    First of all great post,

    I am trying to find where we associate the button with a specific path eg Button 1 links to home.swf and button 3 is gallery.swf.

    Shouldn’t this be in menu.xml?

    Probably stupid question bur asking anyway

  24. Tawhid says:

    Anybody knows how to change the text color on MouseOver on this code?

  25. YoMan says:

    How would you make each button play a different flv movie?

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>