A Flash Developer Resource Site

Results 1 to 10 of 10

Thread: [CS3] OOP: MCs and Buttons as Class Members

  1. #1
    Junior Member
    Join Date
    Apr 2008
    Posts
    7

    [CS3] OOP: MCs and Buttons as Class Members

    I've been working on a signage project for our new office building that will let users see floor plans and tell who is in which office and what their Gtalk status is. So far I've got a working concept (test movie) but as you can see, it doesn't load all the statuses at the start. It's working off of one LoadVars object and the script executes too fast for the variables to be loaded for the other offices. However, the problem is corrected when an individual office is rolled over.

    My intention is to create an object called office that will hold a background MC (the part that changes color), a button (the part that initiates actions), an offices number string, and a LoadVars for each office. Ideally I'd like to be able to instantiate the offices once and then just have the code in the class definition handle the actions so I don't have to define actions for every single office (code for 100 buttons? I don't think so...).

    Here's what I have so far (working with Action Script 2.0):
    Code:
    class office{
    	var officeNumber:String;
    	var backgroundMC:MovieClip;
    	var officeButton:Button;
    	var officeLoadVars:LoadVars;
    	
    	function office(n,mc,button,dx,dy){
    		officeNumber = n;
    		backgroundMC = mc;
    		officeButton = button;
    		
    		//initialize positioning
    		backgroundMC._x = dx;
    		backgroundMC._y = dy;
    		officeButton._x = dx;
    		officeButton._y = dy;
    		
    		//set the displayed office number
    		backgroundMC.number.text = officeNumber;
    		
    		setStatus();		
    	}
    	
    	offcVars.onData = function(success){
    		if(success){
    			//process the data and put it in the tooltip window
    			//    exe- tooltip.name.text = officeLoadVars.name
    			//         tooltip.message.text = officeLoadVars.message
    		}
    	}
    	
    	function changeBGColor(code){
    		//change the bg color of the office bgMC
    		//	either use setTranform or change the _currentframe
    	}
    	
    	function setOfficeStatus(){
    		//php file takes an office number and returns:
    		//	Occupant name or use (person vs storage vs training room)
    		//	Gtalk status (already externally coded for; available, busy, idle, ect.)
    		//  Gtalk status message (exe- Out to lunch; Working from Home)
    		officeLoadVars.load("getOfficeStatus.php?room="+officeNumber);
    		changeBGColor(officeLoadVars.statusCode);
    	}
    	
    	officeButton.onRollOver = function(){
    		revealToolTip();
    		setOfficeStatus();
    	}
    	
    	officeButton.onRelease = function(){
    		revealToolTip();
    		setOfficeStatus();
    	}
    	
    	officeButton.onRollOut = function(){
    		hideToolTip();
    	}
    }
    The idea is to pass in a movie clip and a button already on the stage and have the actions inside the class handle everything that I was typing out manually before. The problem is I'm getting stuck at errors for the button functions I'm trying to define.

    Is it even possible to do what I'm attempting? (If something doesn't make sense, PLEASE let me know).

  2. #2
    Total Universe Mod jAQUAN's Avatar
    Join Date
    Jul 2000
    Location
    Honolulu
    Posts
    2,429
    Hi and welcome to Flashkit!

    You are going to want to write an OfficeButton class. It looks like Office will be your main class so you will likely only be creating one instance of that. From there you could concievebly pass multiple instances of new OfficeButton() to it via a for loop.

    If class OfficeButton{} allowed for a movieclip to be passed in as one of its constructor parameters, you could treat that movieclip as if it were officeButton.

    PHP Code:
    //It would look something like this
    //Office.as
    class Office{
     public function 
    Office(){
       
     }
    }

    //OfficeButton.as
    class OfficeButton{
      public function 
    OfficeButton(mc:MovieClipid:Number){
         
    mc.onRelease = ??
         
    mc.onRollOver = ??
      }
    }

    //then in your flash movie
    for(0100i++){
      var 
    office_btn officeMovieClip.attachMovie("officeLinkage""office"+ii);
      var 
    btn = new OfficeButton(office_btni);


  3. #3
    Junior Member
    Join Date
    Apr 2008
    Posts
    7
    I've had pretty bad luck trying to mix the functionalities of buttons and movie clips so far, so that's why they've been separate entities. If I'm reading this correctly, I can just add my button functionality to the mc using mc.onRelease, etc.?

    Also, to clarify for myself as I have never used the attachMovie method before, say I have an office305 movie clip in my library. To create it as an OfficeButton using this class structure, I will export it for actionscript using the linkage name "officeLinkage". Then the "office"+i could be replaced with "office305" which gives it a stage instance name, and then i is depth (is there anything too significant about depth?).

    Is officeMovieClip something I have to define anywhere else or remember for use anywhere else?

    The main thing I'm worried about is having a LoadVars object for each office, and then using it when someone interacts with the OfficeButton. I would assume that the LoadVars would be a part of the Office class, so could I include the OfficeButton in my Office class?

    (I like the SD site, btw)

  4. #4
    Total Universe Mod jAQUAN's Avatar
    Join Date
    Jul 2000
    Location
    Honolulu
    Posts
    2,429
    Yep, you can treat a movieclip as if it was a button. I actually make a lot of my buttons out of 3 frame movieclips with a stop on the first one. Then I have my onRollOver and onRollOut functions make it gotoAndStop accordingly.

    You could use loadMovie, loadClip or attachMovie. I just used attachMovie for this example because it takes less understanding of importing clips.
    attachMovie takes 3 parameters and should be called on the target clip.

    myContainerMovieClip.attachMovie('myLinkageName', 'myInstanceName', depth);
    No two instances can occupy the same depth.

    So each of your offices would have a unique linkage name. Something like office305, office306, office307 etc. If you were making a literal reference your attachMovie would look like this:

    targetMC.attachMovie("office305", "officeButton"+i, i);
    Note that i is an iterant variable in a for loop

    I just picked a good sounding name when I used officeMovieClip, you should replace that with the name of your movieclip that will contain all the office buttons.

    As far as loading data, I would try not to put asynchronous actions as part of your main classes code flow. It's tough to wrap normal in line logic around load events. I would create Office.as to accept an xml object. You could then load that xml as part of your flash movies script and trigger the Office constructor as part of the onLoad() function for that xml. Loading a text file would work the same way. As long as your Office class knows what to do with the data.

    Say you had a method in the Office class called buildOffices(). And lets say buildOffices loops over the data you imported and creates new OfficeButton instances accordingly.
    If buildOffices's job was to attach each office movie and give it an onRelease, it could use the iterant value of a for loop to match up the button with the data.

    //not sure how your data is structured but could be something like
    public function buildOffices(data){
    for(var i=0; i<data.length; i++){
    var clip = officeMovieClip.attachMovie(data[i][0], 'officeButton'+i, i);
    var btn = new OfficeButton(clip, i);
    }
    }

    Once the data was loaded, your entire app thus far could conceivably look like this:

    myOffice = new Office(myLoadedData);
    myOffice.buildOffices();

  5. #5
    Junior Member
    Join Date
    Apr 2008
    Posts
    7
    So essentially, I could populate an XML document from the database with all the pertinent external-to-flash information and import it as an array. Then upon creating an Offices object, it would loop through the array and create an MC "button" for each office inside a Movie Clip called officeMovieClip (to reference your code) with a matching id. Then inside my "button" class under rollOver and rollOut methods I could just use the ID of the button to reference the data array and get the corresponding data into my tool tip (this is what the button was doing originally).

    That sounds like a good plan as far as the static data goes, but there's still an issue of getting the occupant's dynamic messenger status. It's currently set up to call upon a PHP file with an office number and expects a code and message response. Ideally, it should refresh when the floor is loaded and then every 30 seconds after that or when the office is rolledOver or clicked.

    It should be easy enough to get the individual actions to work inside the "button" onRollOvers and onReleases, but I'm somewhat weary of the overall refreshes, or even the initialization of all the offices. I'm having trouble seeing how to implement that.

    I suppose in the end we could just not worry about the complete refreshes and just focus on the initialization and the single actions... I could ask my coworker to have his API populate an XML file with all the initial statuses and have it update it every so often, so that when the individual buttons are interacted with, they can read in new data from the XML file.

    Is there an easy way to refresh the data array?

  6. #6
    Total Universe Mod jAQUAN's Avatar
    Join Date
    Jul 2000
    Location
    Honolulu
    Posts
    2,429
    If you are going to go with XML, you could just stick with an XML object and traverse that for your data much like you would a multidimensional array. If it's easier to understand by parsing your XML into and array then go for it. Plus if the php can just pass back an xml formated string, you can skip dealing with a text document altogether and just use XML.load('somephp.php')

    But yeah it sounds like you understand. The for loop generates the iterant value which is then used for look up during assignment.

    For real time updates you want to look into opening a socket connection.

    Your biggest problem is trying to get this all working at once. The number one rule of programming is "Never add functionality early."

    Fall back a little and just worry about getting the UI generated. Then worry about making them clickable, then worry about what happens on click. One thing at a time.

  7. #7
    Junior Member
    Join Date
    Apr 2008
    Posts
    7
    Alright, thank you very much for your help. I usually try to keep things separated, but I get into the problem where my design inhibits my ability to add functionality sometimes. (It also doesn't help that I just had to turn in the final project for my Database class x.x).

    I will mess around with the XML to see if I can remember how to do that

    Again, many thanks for your time!

  8. #8
    Junior Member
    Join Date
    Apr 2008
    Posts
    7
    Ok I think I have my concepts aligned, so let me run them by you for sanity's sake

    I have a Floor object that gets created when a user selects a floor. The object is passed a number that determines from the XML object which Office objects (my "buttons") get created.

    I do plan to draw and position all the offices as it just feels safer doing it that way, but as long as I make all the offices in the database/XML match up with an MC in the library (exe- office number 305 matches up with office305:MovieClip in the library) then I can loop through the XML and use eval() to so my execution for me. I'm pretty sure eval() was the missing piece in my conceptualization.

    With that said, considering the following class definitions,
    Code:
    XML:
    <flr>
    	<office>
    		<number>305</number>
    		<use>Rae</use>
    		<sts>Available</sts>
    		<msg>Food found. Back to work.</msg>
    	</office>
    	
    	<office>
    		<number>303</number>
    		<use>Jared</use>
    		<sts>Idle</sts>
    		<msg>Luminisssssssss</msg>
    	</office>
    	
    	<office>
    		<number>301</number>
    		<use>Peter</use>
    		<sts>Offline</sts>
    		<msg>Working from home.</msg>
    	</office>
    </flr>
    ...
    class Floor{
    	
    	public function Floor(xml:XML,toolTip:MovieClip){
    		for(var i = 0; i < xml[0].length; i++)
    			var btn = new Office(eval("office"+xml[0][i]),xml[0][i],toolTip);
    	}
    	
    	public function refreshStatus(xml:XML)
    	{
    		//loop through all the buttons and call their setStatus(xm[0][i].status) function
    	}
    }
    ...
    class Office{
    	private var id:String;
    	
    	public function Office(mc:MovieClip,num:String,tt:MovieClip)
    	{
    		mc.onRollOver = mcRollOver(mc,tt);
    		mc.onRelease = mcRollOver(mc,tt);
    		mc.onRollOut = mcRollOut(mc,tt);
    		id = num;
    	}
    	
    	public function mcRollOver(mc:MovieClip,tt:MovieClip){
    		tt.revealToolTip(id);
    		var myColor = new Color(mc.bg);
    		myColor.setTransform({ra:20,ga:20,ba:20});
    	}
    	
    	public function mcRollOut(mc:MovieClip,tt:MovieClip){
    		tt.hideToolTip();
    		var myColor = new Color(mc.bg);
    		myColor.setTransform({ra:0,ga:0,ba:0});
    	}
    }
    ...
    would it be safe to assume that

    Code:
    floorNum = 3;
    
    ignoreWhite = true;
    xml = new XML();
    xml.onLoad = function(success)
    {
    	if(success)
    		floor = new Floor(xml,toolTip);
    }
    xml.load("xml.php?floor="+floorNum);
    would generate all my objects?

    (just to clarify, in this case, there are office301,office303,office305, and toolTip movie clips on the stage)

  9. #9
    Junior Member
    Join Date
    Apr 2008
    Posts
    7

    Follow up...

    Ok, I believe I have the bases covered, but there's still something that's preventing the movie from meshing properly.

    Here is my floor constructor. When the XML is done loading, the constructor is called, passing in the XML object. It loops through the XML data (provided after the floor script) and references instances on the stage.
    Code:
    class Floor{
    	var count:Number;
    	var btn:Array;
    	
    	public function Floor(xml:XML){
    		for(var i = 0; i < xml.firstChild.childNodes.length; i++)
    		{
    			var officeNum = xml.firstChild.childNodes[i].firstChild.firstChild;
    			var statusColor = xml.firstChild.childNodes[i].childNodes[2].firstChild;
    			
    			trace ("office"+officeNum);
    			trace (statusColor);
    			btn[i] = new Office(eval("office"+officeNum),officeNum,statusColor);
    		}
    		count = i;
    	}
    XML:
    Code:
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <flr>
    	<office>
    		<number>305</number>
    		<use>Rae</use>
    		<sts>0x66CC00</sts>
    		<msg>Food found. Back to work.</msg>
    	</office>
    	
    	<office>
    		<number>303</number>
    		<use>Jared</use>
    		<sts>0xFFCC00</sts>
    		<msg>Luminisssssssss</msg>
    	</office>
    	
    	<office>
    		<number>301</number>
    		<use>Peter</use>
    		<sts>0x999999</sts>
    		<msg>Working from home.</msg>
    	</office>
    </flr>
    The first trace line traces out office305, office303, and office301 in the output box, so I can't tell if the eval is doing what I need it to or not. There are three movie clip instances on the stage called office305, office303, and office301, so I was hoping that using eval would actually pass those instances to the office constructor. I have no idea if this is working or not...


    Here is my office constructor.
    Code:
    class Office{
    	private var id:String;
    	
    	public function Office(mc:MovieClip,num:String,code:String)
    	{
    		mc.onRollOver = mcRollOver(mc);
    		mc.onRelease = mcRollOver(mc);
    		mc.onRollOut = mcRollOut(mc);
    		
    		//mc.setStatus(sCode) = setStatus(mc,sCode);
    		var myColor = new Color(mc.bg);
    		myColor.setRGB(code);
    		
    		id = num;
    	}
    	
    	public function mcRollOver(mc){
    		//tt.revealToolTip(id);
    		mc.gotoAndPlay("over");
    	}
    	
    	public function mcRollOut(mc){
    		//tt.hideToolTip();
    		mc.gotoAndPlay("up");
    	}
    Here's what my individual MCs look like, plain and simple.

    Each frame has a stop(); and there are no other actions associated with it.

    In the bg layer, there is a MovieClip called bg with just a shape within the mc. My goal was to be able to use the setRGB to change the color of this bg clip when the status is read at the very beginning, and then have the mouseOver and Out actions advance the frames so that a highlight appears on the "over" position.

    When I play the movie like this, I get a mouseOver cursor on the three mcs, but no color changes happen or highlights. That aside, I still have to figure out how to change the tooltip data from the button rollOver and rollOut functions, seeing as the tooltip is just sitting on the stage. I can't figure out how to get my classes to interact with external objects and functions in the stage... Is there an easy way to do that? I'm having trouble passing the objects through functions.

  10. #10
    Junior Member
    Join Date
    Apr 2008
    Posts
    7
    Well I think I figured out what my problem is as far as the office "buttons" go...

    In the floor constructor, where I loop through the office nodes of the XML, I'm referring to the linkage offices from the library, and I don't think the Floor class likes that. (I tried replacing eval("office"+officeNum) with office301 and I got an error)

    Perhaps I'm missing the concept of how information is passed between classes and actual entities in the flash movie...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  




Click Here to Expand Forum to Full Width

HTML5 Development Center