A Flash Developer Resource Site

Results 1 to 11 of 11

Thread: How can you add different instances of a symbol?

  1. #1
    Junior Member
    Join Date
    May 2012
    Posts
    17

    How can you add different instances of a symbol?

    Hi,

    I have a symbol in my library that I'd like to see multiplied on the screen, but I don't know how to make multiple instances of it appear.

    I can call one instance of the symbol with the lines:
    var myclip:MovieClip = new symbolname();
    addChild(myclip);

    However if I do it repeatedly, the new instance always replaces the old ones. How can I make multiple instances appear, and is it then possible to refer to them individually in the code?

  2. #2
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    A single display object may only be on the display once. To create more, you need to actually create more
    Code:
    var someSymbol:symbolname = new symbolname();
    addChild(someSymbol);
    someSymbol = new symbolname();
    addChild(someSymbol);
    That will get you two instances of symbolname (which is a terrible name), but they'll be in the same place, and you'll have lost the reference to the first one because it was overridden with the second one. You could use a different variable, then you'd have both references. If you're adding an arbitrary number of them, or you want to process them together later, put your instances in an array.

    Code:
    var symbols:Array = [];
    symbols.push(addChild(new symbolname()));
    symbols.push(addChild(new symbolname()));
    symbols.push(addChild(new symbolname()));
    Now you have 3 of them (still in the same place). You can iterate over them by iterating over the array.
    Code:
    for (var i:int = 0; i < symbols.length; i++){
      symbols[i].x = 10*i;
    }

  3. #3
    Junior Member
    Join Date
    May 2012
    Posts
    17
    Thanks. How would I go about adding an addEventListener to all instances of the symbol? (for example, so that the instance is destroyed when the user clicks on it, but not the other instances) Is that possible?

  4. #4
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Since you say you want the listener on all instances, I'd suggest adding it to the class for that symbol. Let's say you have a class called Thing associated with that symbol.
    Code:
    package{
      public class Thing extends MovieClip{
         public function Thing(){
            addEventListener(MouseEvent.CLICK, onclick);
         }
    
         public function onclick(event:MouseEvent):void{
            //do everything to destroy self.
            dispatchEvent(new EnemyEvent(EnemyEvent.DIE, true));
         }
      }
    }
    Since you have your instances in an array in the main timeline, part of "destroy" probably involves removing that instance from that array. I'd suggest dispatching a new event from the dying instance, and handling that in the main timeline. See the dispatchEvent line above. I'd also like to make a specific class for the enemy events, of which DIE would be one constant.
    Code:
    package {
      public class EnemyEvent extends Event{
        public static var DIE:String = "DIE";
        //... implement everything needed, such as constructors.
      }
    }
    The main timeline will listen for the DIE events and do the necessary removals.
    Code:
    addEventListener(EnemyEvent.DIE, enemyDie);
    
    function enemyDie(e:EnemyEvent):void{
      var nme:DisplayObject = DisplayObject(e.target);
      var index:int = symbols.indexOf(nme);
      if(index != -1){
        symbols.splice(index, 1);
      }
      if (contains(nme)){
        removeChild(nme);
      }
    }
    Last edited by 5TonsOfFlax; 06-05-2012 at 10:34 AM.

  5. #5
    Junior Member
    Join Date
    May 2012
    Posts
    17
    Sorry for the dumb questions but I'm new to this.

    To create a class associated with the symbol, I create a new class and I type your first section of code in it (replacing "MovieClip" with the symbol's name) - correct?

    Where do I write the second portion of code? I take it I have to create a class named EnemyEvent? The thing is when I do this it gives me an error when I run the program: "The definition of base class Event was not found"

    And the last portion of code is to be inserted in the timeline in frame 1?

  6. #6
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    No, you don't replace "MovieClip" with the symbol name. You should have a field somewhere in the symbol properties for the associated class. You could change "Thing" to something more descriptive of your symbol, even the symbol name itself, but I strongly recommend that you have the class begin with a capital letter. It is by far the most common convention.

    The second portion of code should go in a file named EnemyEvent.as in the root of your classpath. The same place as your fla and Thing.as or whatever you've named your class. You will probably have to add various import statements such as
    Code:
    import flash.events.Event;
    You'll probably need to add some imports to the first on too.
    Code:
    import flash.events.MouseEvent;
    import flash.display.MovieClip;
    If your symbol does not have frames or frame script, then you should use Sprite rather than MovieClip.

    The last section of code should be somewhere on your timeline, yes. I wrote it that way because I assumed you did not have a document class. If you do, then you should adapt it and put it in there.

  7. #7
    Junior Member
    Join Date
    May 2012
    Posts
    17
    I'm not sure what a constructor is exactly. If I run the program as is I get the error "No default constructor found in base class flash.events:Event." but I don't know what to put there.

    Isn't there an easier way to do this? It seems like an awful lot of code for just having an object destroyed when clicking on it

  8. #8
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    Yes, you do not need the EnemyEvent class. It just provides strong type-checking. You can use a plain event with a made up event type.
    Change the dispatchEvent line like so:
    Code:
    dispatchEvent(new Event("die", true));
    And the listening lines like so:
    Code:
    addEventListener("die", enemyDie);
    
    function enemyDie(e:Event):void{
    //...
    And you won't need EnemyEvent at all.

    And if you define "easier" as "easier to understand without understanding classes", then you could skip the Thing class and just add the listener to each Thing after creating it, and define that click listener in the timeline as well.
    Code:
    var things:Array = [];
    for (var i:int = 0; i < 10; i++){
      var thing:Thing = new Thing();
      thing.x = i*thing.width;
      addChild(thing);
      things.push(thing);
      thing.addEventListener(clickThing);
    }
    
    function clickThing(e:MouseEvent):void{
      var thing:DisplayObject = DisplayObject(e.target);
      var idx:int = things.indexOf(thing);
      if (idx != -1){
         things.splice(idx, 1);
      }
      if (contains(thing)){
        removeChild(thing);
      }
    }
    I don't like doing this, as it makes no effort to distinguish between the responsibilities of Thing and the main timeline. Adding more complex behavior later will be more difficult, and the code is not well organized. But it should work.

  9. #9
    Junior Member
    Join Date
    May 2012
    Posts
    17
    Thanks.

    I have managed to do it by placing this code in the main timeline:

    Code:
    import flash.events.MouseEvent;
    
    for (var i:int = 0; i < (...), i++)
    {
    var symb:MovieClip = new Symbolclassname();
    symb.x = ...
    symb.y = ...
    addChild(symb);
    symb.addEventListener(MouseEvent.CLICK, killsymbol);
    }
    
    function killsymbol(event:MouseEvent):void
    {
    removeChild(event.currentTarget as MovieClip);
    }
    It does all I want it to. I still have a question though, is it then possible to count the number of instances of the symbol on the screen? So that the game will react differently depending on how many symbols are still left.

    edit: In this instance I guess I can calculate it by adding 1 to a variable every time the killsymbol function is called. But in a more elaborate version of this program I will make the symbols appear one after another, so it will no longer be possible to count them this way, as the variable will tell me how many symbols have been killed, but not how many have appeared.
    Last edited by FlashAahaah; 06-06-2012 at 03:47 PM.

  10. #10
    Will moderate for beer
    Join Date
    Apr 2007
    Location
    Austin, TX
    Posts
    6,801
    If you put the instances in an array (and removed them from the array when killed), you could use the array length as the current enemy count.
    Alternatively, you could put them in a dedicated container Sprite and use that Sprite's numChildren property.

  11. #11
    Junior Member
    Join Date
    May 2012
    Posts
    17
    Thanks. I finally got it.

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