Aaron Stewart
Aaron Stewart

Reputation: 13

Easy way to make a lot of buttons share a function? AS3

I am trying to do a simple light-up pegboard in flash. I have finished the general logic for 1 peg but there will be a total of 2,300 pegs and I don't want to have to add an event listener to each movieclip.

Here is my code:

import flash.events.Event;
var my_color:ColorTransform = new ColorTransform();
movieClip_1.addEventListener(MouseEvent.MOUSE_UP, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{

    if (my_color.color == 0)
    {
        my_color.color = 0x0000FF;
        event.target.transform.colorTransform = my_color;
    }
    else if (my_color.color == 255)
    {
        my_color.color = 0x00FF00;
        event.target.transform.colorTransform = my_color;
    }
    else if (my_color.color == 65280)
    {
        my_color.color = 0xFF0000;
        event.target.transform.colorTransform = my_color;
    }
    else if (my_color.color == 16711680)
    {
        my_color.color = 0xFFFFFF;
        event.target.transform.colorTransform = my_color;
    }
    else if (my_color.color == 16777215)
    {
        my_color.color = 0x000000;
        event.target.transform.colorTransform = my_color;
    }
    else
    {
        trace(my_color.color);
    }   
}

[Screenshot of Final Product]

Upvotes: 0

Views: 57

Answers (2)

Amy Blankenship
Amy Blankenship

Reputation: 6961

One way to do it is loop through all the children of the parent of your 2300 pegs.

for (var i:int=0; i<numChildren; i++) {
  var clip = getChildAt(i);
  if (clip.name.indexOf('movieClip_')==0) {
     clip.addEventListener((MouseEvent.MOUSE_UP, fl_MouseClickHandler);
  }
}

Another way to do it is to add a handler to the entire parent clip and then in the handler check and see if what was clicked is one of your pegs. But you have to disable mouseChildren on the child clips for that to work.

Note that you may want to look at replacing that big if/then statement with switch/case, which is clearer and more compact in this type of situation.

Upvotes: 0

BadFeelingAboutThis
BadFeelingAboutThis

Reputation: 14406

Here are 3 ways to accomplish this:

  1. Put the code on the peg's own timeline. (or make a class file, and attach it to your peg object). This will re-use the same code for each peg instance automatically. Just take the same code you have, but use the this keyword instead of a hard reference to the movie clip:

    var my_color:ColorTransform = new ColorTransform();
    this.addEventListener(MouseEvent.MOUSE_UP, fl_MouseClickHandler);
    function fl_MouseClickHandler(event:MouseEvent):void
    {
        //.....
    
  2. Make a container Sprite/MovieClip and have all the pegs be the sole children of it. Then iterate over all the children of that container and attach the listener:

    //loop through all children of the container and add an event listener
    var i:int = container.numChildren;
    
    while(i--){
        container.getChildAt(i).addEventListener(....);
    }
    

    This is good because you don't have to give them instance names, which would be quite tedious.

  3. Attach a click listener to a common parent of all pegs, and use the target property of the event to see if the click was on a peg. Assuming you have right-clicked your peg library object, gone to properties and checked "export for actionscript" and given it the Class name "MyPeg", you could do this:

    commonParent.addEventListener(MouseEvent.CLICK, parentClick);
    
    function parentClick(e:Event):void {
        if(e.target is MyPeg){
            //it's a PEG, do something
        }
    }
    

    Now, depending on how your peg object is structured, target could also refer to a child of your peg (instead of the peg itself). To avoid this if it's applicable, you can disable mouse input on the children of the peg. So on the first frame of your peg object, you could this: this.mouseChildren = false;


Now, even better (less tedious) would be to instantiate your pegs through code too. So as mentioned earlier, export your peg for actionscript in it's properties, and give it a class name ("MyPeg" for my example). Then something along these lines:

var curRow:int = 0;
var curCol:int = 0;

var totalRows:int = 25;
var totalCols:int = 92;

var startingY:int = 10;
var startingX:int = 10;

var padding:int = 2; //gap between pegs

var curPeg:MyPeg;

while(true){
    //create the peg, and add it to the display.
    curPeg = new MyPeg();
    addChild(curPeg);

    //add the click listener to this peg
    curPeg.addEventListener(MouseEvent.CLICK, fl_mouseClickHandler);

    //assign the position of this peg
    curPeg.x = startingX + (curCol * (curPeg.width + padding));
    curPeg.y = startingY + (curRow * (curPeg.height + padding));

    //increment the column
    curCol++;

    //check if we've reached the last column in the row
    if(curCol >= totalCols - 1){
        //yes, so reset the column to 0 and increment the row
        curCol = 0;
        curRow++;

        //break out of the loop if the curRow exceeds or is equal to the total rows var
        if(curRow >= totalRows) break;
    }
}

This way you could change your grid size simply by modifying the number assigned to totalCols and totalRows - no need to tediously move around 2300 objects in FlashPro.

Upvotes: 2

Related Questions