Skip to main content
Participating Frequently
January 15, 2014
Question

Populating a dynamic array with objects and managing it in runtime.

  • January 15, 2014
  • 1 reply
  • 1714 views

So I'm another stuck firstyear. I'll try and make my question compact. I'm using Flash CS6 and have drawn an animated character on the stage that consists of separate parts that are animated and its head is a separate class/symbol entirely because it has not only animation, but a state switch timeline as well. This said Head extends the Main that is the character MovieClip.

I am using a dynamic array to store and .push and .splice objects of another class that would collide with this said Head.

I also discovered the super() function that is implicitly called as the constructor of the parent in any child class that extends the parent, in this case Head extends Main. The issue is that my collidable object array is populated within the main, within the function that spawns every next collidable object with a TimerEvent. This said function then gets called twice due to the super() call.

I have tried putting this super() call into an impossible statement in my child class, but it doesn't change a thing, and it was said that this method is unsafe so I don't even know if it should be working.

However what confuses me the most is when I trace() the .length of my collidable object array at the end of that function. As I said earlier, the original function both spawns an object after a period of Timer(1000) and adds it to the stage as well as adds the object onto the object array, but the super() constructor only duplicates the length call and a creates a copy of the object on the stage, but it does not add the second copy of the object onto the array. The trace() output goes on like so:

1

1

2

2

3

3

4

4

etc.

I wonder why and I'm really stumped by this.

Here is the code in question:

public class Main extends MovieClip {

                    public var nicesnowflake: fallingsnow;

                    var nicesnowflakespawntimer: Timer = new Timer(1000);

                    public var nicesnowflakearray: Array = new Array();

                    public function Main() {

                              nicesnowflakespawntimer.addEventListener(TimerEvent.TIMER, nicesnowflakespawn);

                              nicesnowflakespawntimer.start();

                    }

                    public function nicesnowflakespawn(event:TimerEvent) : void {

                              nicesnowflake = new fallingsnow;

                              nicesnowflake.x = Math.random()* stage.stageWidth;

                              nicesnowflake.y = - stage.stageHeight + 100;

                              nicesnowflakearray.push(nicesnowflake);

                              stage.addChild(nicesnowflake);

                              trace(nicesnowflakearray.length);

                              for (var i:Number = 0; i < nicesnowflakearray.length; i++){

                                        nicesnowflakearray.addEventListener(Event.ENTER_FRAME, snowhit);

                              }

                    }

                    public function snowhit(event:Event) : void {

                              if (nicesnowflakearray[0].y >= 460){

                                        if (nicesnowflakearray[0].y == stage.stageHeight) {

                                        nicesnowflakearray.splice(nicesnowflakearray.indexOf(nicesnowflake), 1);

                              }

                              //if (this.hitTestObject(nicesnowflake)){

                                        //trace("hit");

                              }

                    }

I am also fiddling with the collision, but I believe that it would sort itself out when I deal with the array pop and depop properly. However I'm pasting it anyway in case the issue is subtly hidden somewhere I'm not looking for it. And here is the child class:

public class Head extends Main {

                    public function Head(){

                              if (false){

                                        super();

                              }

                              this.stop();

                    }

          }

}

So like what happens at the moment is that the array gets populated by the first object that spawns, but there is two objects on the stage, then when the objects reach stage.460y mark the array splices() the one object away and displays an error:

"#1010: A term is undefined and has no properties.

          at Main/snowhit()"

then when the next object spawns, it repeats the process. Why does it trace the array.length as "1, 1, 2, 2, 3, 3, 4, 4, 5, 5, etc" until the despawn point and then goes on to display an error and then starts from 1 again, because if the array length is more than one object at the time when the first object of the array gets spliced away, shouldn't it go on as usual, since there are other objects in the array?

Thank you very much to whomever will read this through.

This topic has been closed for replies.

1 reply

Inspiring
January 15, 2014

There are multiple problems:

1. You should add eventlisteners for your objects only once, but you add eventlisteners every time your timer runs to all of your snowflakes, again and again:

                              for (var i:Number = 0; i < nicesnowflakearray.length; i++){
                                        nicesnowflakearray.addEventListener(Event.ENTER_FRAME, snowhit);
                              }

change it to

nicesnowflake.addEventListener(Event.ENTER_FRAME, snowhit);

I don`t see why its even necessary to employ this snowflakearray, it would be much straight forward if you simply let the snowflakes take care of themselves.

2. Then you have to change your enterframe function accordingly

public function snowhit(event:Event) : void {
                              if (e.currentTarget.y >= 460){
                                        if (e.currentTarget.y == stage.stageHeight) {

                                        e.currentTarget.removeEventlistener(Event.ENTER_FRAME, snowhit);
                                        removeChild(e.currentTarget);
                              }

                    }

3.

                              //if (this.hitTestObject(nicesnowflake)){
                                        //trace("hit");
                              }

since "this" is a reference to the Main class (root) it surely won`t function as you intend it to.

                              if (false){
                                        super();
                              }

makes no sense to use a condition that can never be true

SkalbeAuthor
Participating Frequently
January 15, 2014

1. I moved the whole snowflakespawner etc out of the main into a separate snowflake symbol class.

2. The hitTest I posted was a rudiment and was previously in a different class, where this. was the head of the character.

3. Exactly. I found that you could force the program NOT to call super() at all by encasing it in an impossible statement, but I don't think I understood it fully and am not doing something right.

4. I have a different problem now. There is nothing left in my main and I just need to call in it the main function of the child snowflake class in order to execute everything like before. How do I simply call a child function in a parent class?

SkalbeAuthor
Participating Frequently
January 15, 2014

I assume the underscores are necessary for some reason.

No they are not, they are merely there, because "parent" and "child" are reserved keywords in AS3

I don't believe I have anywhere an object of the Main class

Every Flash file has an instance of the Main class, its called "root"

so in every flash file you can call "root" and will reach the highest object.

instead of writing

_Main._nicesnowflake._fallingsnow();

you can write

root.nicesnowflake.fallingsnow();

or if you call from Main you can simply write

    

this.nicesnowflake.fallingsnow();

this will trigger the public function that belongs to the nicesnowflake instance


Yeah I tried that. It didn't work. It provided me with an error in the output field saying sometihng about static class function or something. Although I'm not using `static` for anything.

In any case I just moved it all back into the Main and fixed it partially.

I fixed the double call of trace and the constructor duplication and life is almost beautiful.

The issue I've got now is that I can't seem to find the Head object on the stage in order to check its .y value against .y values of the snowflake objects that are falling down. So to make a manual collision test.

The head is just an empty class that extends MovieClip and has this.stop(); in it in order for it to enter the program in it's default state and not animate continuously.

And then I want to use my manual collision like so:

public function snowhit(event:Event) : void {

                              if ((nicesnowflakearray[0].y == Head.y) || (nicesnowflakearray[0].y == stage.stageHeight)) {

                                        nicesnowflakearray.splice(nicesnowflakearray.indexOf(nicesnowflake), 1);

                              }

but it says "1119: Access of possibly undefined property y through a reference with static type Class". when I change the hardcoded value in the first statement parameter bracket to `Head.y`.

Which is also the same thing it said when I tried calling that child function in the main with the same syntax that you advised.

Thanks for bearing with me, Mocca.