Flash CS5 reference a display object in the constructor of a non-document class

后端 未结 3 1434
感动是毒
感动是毒 2021-01-25 02:17

After learning of this excellent method of accessing an object placed on the stage in Flash CS5 in a class other than the document class (found in this thread), I have run into

相关标签:
3条回答
  • 2021-01-25 02:57

    The fact that you can not access the instances on the stage in a class' constructor but can in another function of the class (that you call later I assume) makes me think that stage is not available to your constructor when it is being called.

    Check to make sure that your Game.as document class is set up like this, although it probably is since you followed my method:

    public function Game() {
        addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
        //DO NOT CREATE CLASS INSTANCES IN HERE
    }
    
    private function init(e:Event):void{
        //In here is where we create instances of classes
    }
    

    Additionally, set your stage data type to Stage instead of Object in your Player class's constuctor's paramater for good coding practice.

    0 讨论(0)
  • 2021-01-25 03:04

    The problem that you're having is that you are instantiating your controller class before you have a stage object to pass to it. You must wait until after the ADDED_TO_STAGE event is fired to instantiate everything else:

    public class Game extends MovieClip {
        private var _player:Player;
        private var _controller:Controller;
    
        public function Game():void
        {
            addEventListener(Event.ADDED_TO_STAGE, added);
        }
        private function added(evt:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, added);
            _player = new Player(stage);
            _controller = new Controller(_player,stage);
            addChild(_player);
        }
    }
    

    There is a better way

    You do not need to pass stage though to your player and controller. If you just pass a reference to this, you will pass a reference to the document class. This is a better practice to get into as it prepares you for more advanced programming approaches like design patterns.

    So you would have your document class:

    public class Game extends MovieClip {
        private var _player:Player;
        private var _controller:Controller;
    
        public function Game():void
        {
            addEventListener(Event.ADDED_TO_STAGE, added);
        }
        private function added(evt:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, added);
            _player = new Player(this);
            _controller = new Controller(_player,this);
            addChild(_player);
        }
    }
    

    and in your player class:

    public class Player extends MovieClip {
        private var docRef:Game;
        private var _lights:uint;
    
        public function Player($docRef:Game):void {
            this.docRef = $docRef;
            docRef.greenLight1.visible=false; //no longer needs to wait for player to be on the stage
        }
    }
    

    The advantage is obvious, since you know that you document class is on the stage, Player does not need to be on the stage before it can interact with it. It does not need ever be on the stage. If you need stage, say for adding listeners like you do in the Controller, you can use the documents stage property:

    docRef.stage.addEventListener ...
    
    0 讨论(0)
  • 2021-01-25 03:15

    stage is a property of DisplayObject only accessible/defined once it has been added to the DisplayList (ie - added to something via addChild())

    You won't have any luck accessing stage from a class constructor unless it's the document class.

    As mentioned, you can shift the contents of your constructor to a custom function which is called once Event.ADDED_TO_STAGE has been triggered.

    For example, here's a demo class:

    public class Thing extends DisplayObject
    {
        /**
         * Constructor
         */
        public function Thing()
        {
            // Add listener
            addEventListener(Event.ADDED_TO_STAGE, _added);
        }
    
        /**
         * Called once this has been added to the display list
         * @param e Event.ADDED_TO_STAGE
         */
        private function _added(e:Event):void
        {
            // Discard listener
            removeEventListener(Event.ADDED_TO_STAGE, _added);
    
            // My initial code
            trace(stage + " is accessible");
        }
    }
    

    Which we then create an instance of:

    var thing:Thing = new Thing(); // nothing happens
    

    And then add to the stage/current container:

    addChild(thing); // output: [Object Stage] is accessible
    

    As for accessing greenLight1, this should be achievable easily via either of the following:

    stage.greenLight1;
    stage["greenLight1"];
    

    Also, you might want to replace:

    public function Player(stage:Object):void
    

    With:

    public function Player(stage:Stage):void
    
    0 讨论(0)
提交回复
热议问题