0
votes

I'm having a problem with this menu tutorial I followed from ASGamer. I have done and used most, if not all of the tutorials from that site.

Anyway my problem is their base menu class;

package com.game.scripts.menu
{
    import flash.display.MovieClip;
    import flash.display.Stage;
    import flash.events.Event;

    import com.caurina.transitions.Tweener;

    public class BaseMenu extends MovieClip
    {
        public var stageRef:Stage;
        public var loadNext:BaseMenu;

        public function BaseMenu()
        {
            alpha = 0;
        }

        public function Unload(loadMe:BaseMenu = null):void
        {
            if(loadMe != null)
            {
                loadNext = loadMe;
            }

            Tweener.addTween(this, {alpha:0, time:0.7, onComplete:Remove});
        }

        public function Remove():void
        {
            //dispatchEvent(new Event("menuRemoved"));
            if(stageRef.contains(this))
            {
                stageRef.removeChild(this);
            }

            if(loadNext != null)
            {
                loadNext.Load();
            }
        }

        public function Load():void
        {
            stageRef.addChild(this);
            Tweener.addTween(this, {alpha:1, time:0.7});
        }
    }
}

Whenever I use the Remove() function, which is also used by the Unload() function, my stage.addEventListeners breaks. Particularly my stage.addEventListener(KeyboardEvent.KEY_UP, KeyUpHandler) in another class does not execute at all.

Is there another way I can remove the menus without breaking the stage? Or if you know of a better menu tutorial, a link would be greatly appreciated :D

EDIT I just commented everything in the Remove() function and key handler is still not working.

EDIT 2 The first edit only applied to my MainMenu, my other menus seem fine. I commented this part;

if(stageRef.contains(this))
{
    stageRef.removeChild(this);
}

and my KeyUpHandler works fine. So I'm assuming that flash will not remove the movieclips for me, or will I be fine and it will be removed?

2
That is a pretty bad tutorial. Here is a very good one about building a complete game. gamedev.michaeljameswilliams.comFeltope
I finally solved the problem. For some reason the key up handler doesnt register unless i click on the screen after a new menu loads.RamenNoodles

2 Answers

0
votes

I can only guess that the Sprite you are giving to the menu class for the stageRef has no reference after you call remove, and so get garbage collected, so you no longer get any key events.

Two suggestions:

  • Make sure you are setting the appropriate value for the stageRef
  • Make sure that you are using a strong reference in your keyboard listener to make sure the stage is not cleaned up.
0
votes

EDIT: come to think of it you don't need to do this if your BaseMenu is derived from sprite or MovieClip I am pretty sure. so just change stageRef.removeChild() to stage.removeChild()

your stageRef isn't actually pointing at the real stage. (sort of)

Also you should try to get used to using ADDED_TO_STAGE events.

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

    public class MainDocument extends Sprite
    {
        private var myMenus:BaseMenu;

        public function MainDocument() 
        {
            addEventListener(Event.ADDED_TO_STAGE, initMain);
        }

        private function initMain(e:Event):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, initMain);

            myMenus = new BaseMenu();
            addChild(myMenus);
        }

    }

}

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

    public class BaseMenu extends Sprite
    {
        public function BaseMenu() 
        {
            addEventListener(Event.ADDED_TO_STAGE, initBanseMenu);
        }

        private function initBanseMenu(e:Event):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, initBanseMenu);

            trace(stage.stageHeight);
        }

    }

}

As you can see from the trace the stage is accessible without the reference.

This should also work just fine. (the actually stage is 'stage' not 'Stage' so make sure your sending 'stage' to your BaseMenu constructor.

public var stageRef:Stage;

public function BaseMenu(stageRef:Stage)
{
    this.stageRef = stageRef;
    alpha = 0;
}

Ok here you can put these files in a flashdevelop project or whatever your using and test it ;-).

package src 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.ui.Keyboard;

    public class MainDocument extends Sprite
    {
        public var myMenuTest:BaseMenu;
        public var mySubMenuTest:SubMenu; 

        public function MainDocument() 
        {
            addEventListener(Event.ADDED_TO_STAGE, initMain);
        }

        private function initMain(e:Event):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, initMain);

            myMenuTest = new BaseMenu(stage);
            myMenuTest.x = stage.stageWidth / 2;
            myMenuTest.y = stage.stageHeight / 2;
            //myMenuTest.Load(); // we can load our Main menu now if we want.

            mySubMenuTest = new SubMenu(stage);
            mySubMenuTest.x = 100;
            mySubMenuTest.y = 100;

            stage.addEventListener(KeyboardEvent.KEY_UP, handleKeyUp);
        }

        // for testing purposes.
        private function handleKeyUp(e:KeyboardEvent):void 
        {
            if (e.keyCode == Keyboard.UP)
                myMenuTest.Unload(mySubMenuTest);
            else if (e.keyCode == Keyboard.DOWN)
                mySubMenuTest.Unload(myMenuTest);
            else
                trace(e.keyCode);
        }
    }
}

package src 
{
    import flash.display.Sprite;
    import flash.display.Stage;

    public class BaseMenu extends Sprite
    {
        public var stageRef:Stage;
        public var loadNext:BaseMenu;

        public function BaseMenu(stageRef:Stage) 
        {
            this.stageRef = stageRef;
        }

        public function Unload(loadMe:BaseMenu = null):void
        {
            if (loadMe != null)
            {
                loadNext = loadMe;
            }
            Remove(); // add your tween.
        }

        public function Load():void
        {
            // this is just so we can have something to see for the test.
            drawTest();
            stageRef.addChild(this);
            // add your tween
        }

        public function Remove():void
        {
            if (stageRef.contains(this))
                stageRef.removeChild(this);

            if (loadNext != null)
                loadNext.Load();
        }

        protected function drawTest():void
        {
            graphics.clear();
            graphics.lineStyle(1, 0);
            graphics.beginFill(0xccccff);
            graphics.drawCircle(0, 0, 20);
            graphics.endFill();
        }
    }
}

package src 
{
    import flash.display.Stage;

    public class SubMenu extends BaseMenu
    {
        public function SubMenu(stageRef:Stage) 
        {
            super(stageRef);
        }
    }
}

This should explain how what I meant works. To test this program just load it up in debug mode and use Up or Down arrow keys to switch between the two menu classes. hitting any other key no matter what menu is up will trace the keyCode to standard out. (debug output window). Obviously 1 class per file. Hope this clears it up.