David
David

Reputation: 887

(AS3) Functions

I managed to fix the whole null stage error by following MJW's guide on debugging Error #1009. But now the function that initializes the bullets doesn't get called.

Snippets:

if (stage) {
 init();
} else {
addEventListener(Event.ADDED_TO_STAGE, init);               
}

...

private function init(event:Event = null) {

    removeEventListener(Event.ADDED_TO_STAGE, init);
    stage.addEventListener(Event.ENTER_FRAME, shoot);


}

...

private function shoot(event:Event) {

    var bullet:EnemyBullet = new EnemyBullet();

    stage.addChild(bullet);

    bullet.x = enemy.x;
    bullet.y = enemy.y;

    bullet.theta = Math.random() * 360;

    bManager.bulletVector.push(bullet);


}

Note that when I put trace() within the second two functions, nothing happens, but the addEventListener() in the first snippet does get called (or so I think).

Upvotes: 0

Views: 218

Answers (2)

Jason Sturges
Jason Sturges

Reputation: 15955

As a general practice, stage should not be referenced - especially in your case, where your reference is solely to add instances of your bullet class. If it's a matter of z-index, you could instead have a layer in which bullets are placed on top of other display objects on the display list.

Besides complexities loading multiple SWFs on a single stage, your code would become nice isolated functional units by adding display objects to their own hierarchy of the display list. Or, you could leverage a MVC pattern whereby a controller manipulated views.

In order for your code to work, that class must either be the main function of the SWF or added to stage.

If it's the main function of the SWF, init() will be called.

Otherwise, assure it's getting added to the display list via an addChild().

Do you really intend to fire a bullet every frame? That could be 24 to 60 bullets a second. You might want to throttle that with some probability whether a bullet with fire.

Say this was a battlefield, and your battlefield class was added to stage, it could be implemented as this:

package
{
    import flash.display.Sprite;
    import flash.events.Event;

    [SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
    public class Battlefield extends Sprite
    {
        public function Battlefield()
        {
            if (stage)
                init();
            else
                addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }

        protected function addedToStageHandler(event:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            init();
        }
        protected function init():void
        {
            addEventListener(Event.ENTER_FRAME, frameHandler);
        }

        protected function frameHandler(event:Event):void
        {
            var odds:Number = Math.random();

            trace((odds < 0.1 ? "Fire!   " : "Skip...") + "Odds were: " + odds);
        }

    }
}

Which would output:

Skip... Odds were: 0.3539872486144304
Skip... Odds were: 0.742108017206192
Fire!   Odds were: 0.025597115512937307
Skip... Odds were: 0.7608889108523726
Fire!   Odds were: 0.08514392375946045 
Skip... Odds were: 0.27881692815572023

Beyond Stage3D, I've never been fond of this initialization pattern, as you could just as easily rely on stage events, as in:

package
{
    import flash.display.Sprite;
    import flash.events.Event;

    [SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
    public class Battlefield extends Sprite
    {
        public function Battlefield()
        {
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }

        protected function addedToStageHandler(event:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
            addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);

            addEventListener(Event.ENTER_FRAME, frameHandler);
        }

        protected function removedFromStageHandler(event:Event):void
        {
            removeEventListener(Event.ENTER_FRAME, frameHandler);

            removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
            addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        }

        protected function frameHandler(event:Event):void
        {
            var odds:Number = Math.random();

            trace((odds < 0.1 ? "Fire!   " : "Skip...") + "Odds were: " + odds);
        }

    }
}

Therefore, upon added to stage the class initiates its actions, and upon removed from stage the class terminates its actions.

Upvotes: 1

Daniel
Daniel

Reputation: 35734

I think the issue is in the first block.

you are checking for stage, if stage is not null, then use a added to stage listener.

you should only be using addEventListener(Event.ADDED_TO_STAGE, init);

however, this is assuming that the class is DisplayObject subclass, objects that do not get added to stage cannot call the ADDED_TO_STAGE listener

Upvotes: 0

Related Questions