简体   繁体   中英

Actionscript 3: How do I access the properties of the document class?

When I try to access some of the private properties of the document class from another class, it outputs this error:

1119: Access of possibly undefined property _player through a reference with static type flash.display:Stage.

Here's the code from the document class:

    package 
{
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.utils.Timer;
    import flash.events.TimerEvent;
    import flash.ui.Keyboard;
    import collision;
    import player;
    import ground;

    public class engine extends MovieClip
    {
        public var _player:player;
        private var _ground:ground;
        private var _collision:collision;
        private var _right:Boolean;
        private var _space:Boolean;
        private var _left:Boolean;
        private var _touchGround:Boolean;
        private var _jump:Boolean;
        private var _jumpVel:int;
        private var _q:int;
        private var _vx:int;
        private var _vy:int;

        public function engine()
        {
            _player = new player();
            _ground = new ground();
            _collision = new collision();
            addChild(_player);
            addChild(_ground);
            _player.x = stage.stageWidth/2 - _player.width/2;
            _player.y = stage.stageHeight/2 - _player.height/2;
            _ground.x = stage.stageWidth/2 - _ground.width/2;
            _ground.y = stage.stageHeight/2 - _ground.height/2;
            _ground.y += 150;
            _ground.x += 300;
            _q = 0;
            stage.addEventListener(Event.ENTER_FRAME, enterFrame);
            stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
            stage.addEventListener(KeyboardEvent.KEY_UP,keyUpHandler);
        }
        private function enterFrame(e:Event) 
        {
            if(_right)
            {
                if(_vx > 15) 
                {
                    _vx = 15;
                }
                _vx += 2;
            }
            if(_left) 
            {
                if(_vx < -15)
                {
                    _vx = -15;
                }
                _vx -= 2;
            }
            if(_space && _touchGround)
            {
                _jump = true;
            }
            if(_jump)
            {
                _jumpVel = 20 - _q;
                if(_q == 20)
                {
                    _q = 0;
                    _jumpVel = 0;
                    _jump = false;
                }
                else
                {
                    _ground.y += _jumpVel;
                    _q ++;
                }
            }
            _collision.detectCollisions();
            _ground.x -= _vx;
            _ground.y += _vy;
            if(_vx > 0)
            {
                _vx--;
                if(_vx < 0)
                {
                    _vx = 0;
                }
            }
            else if(_vx < 0)
            {
                _vx++;
                if(_vx > 0)
                {
                    _vx = 0;
                }
            }
            if(_vy > 0) 
                {
                    _vy = 0;
                }
            else if(_vy < -10) 
                {
                    _vy = -10;
                }
                trace(_vy);
        }

        private function keyDownHandler(e:KeyboardEvent)
        {
            if(e.keyCode == Keyboard.RIGHT)
            {
                _right = true;
            }
            if(e.keyCode == Keyboard.LEFT) 
            {
                _left = true;
            }
            if(e.keyCode == Keyboard.SPACE)
            {
                _space = true;
            }
        }
        private function keyUpHandler(e:KeyboardEvent)
        {
            if(e.keyCode == Keyboard.RIGHT)
            {
                _right = false;
            }
            if(e.keyCode == Keyboard.LEFT) 
            {
                _left = false;
            }
            if(e.keyCode == Keyboard.SPACE)
            {
                _space = false;
            }

        }
    }
}

Here's the code from the 'collision' class.

package
{

    import flash.display.MovieClip;
    import player;
    import engine;

    public class collision extends MovieClip
    {

    private var _playerCol:player = engine._player;


        public function collision()
        {
        }
        public function detectCollisions():void
        {
            _playerCol.y += 7;
        }
    }
}

I'm trying to access the property '_player' from the collision class, but am getting an error.

At the moment you are trying to access _player as if it is a static member of the Engine class. You could make the _player static but that can lead to code smell. A safe way would be to pass a reference into the constructor:

private var _engine:Engine
private var _playerCol:player;
public function collision(engine:Engine){        

   _engine = engine;
   _playerCol = _engine._player
}        

and so in your Doc class you would have this line

_collision = new collision(this);

PS. As a tip classes should really have a capital at the start, and if a variable is going to be public remove the underscore, otherwise leave the variable as private and create public properties for it. Also, you might want to think about changing your structure as it is somewhat clumsy. I recommend having a look into component entity systems.

Root._player doesn't exist. Try accessing it via the engine class.

So, if an engine object exists at the root and is called _engine, you can access _player like the following:

var plyr:player = _engine._player;

EDIT: The collision class doesn't "know" about the engine class; they both exist separately from one another so there's no way to get them to communicate with each other without doing something different. One method, mentioned in comments, is to make the _player property static in engine. So

public static var _player:player;

Another way would be to make the engine class a singleton (as mentioned in another answer).

Another way would be to pass the instance of the engine class to the collision class; that way the collision class is able to "see" the instance variables (properties) available in engine. To do that, you could do something like:

// do this inside the engine constructor
_collision = new collision();
_collision._engine = this;

(Collision should have a var called _engine:engine, to do this, of course.)

You may want to step back from your design and think about how each part should interact with one another. It's possible that there's a different way to do things which will make each object better able to communicate with one another (or, by separating concerns, take responsibility for what each class is supposed to do without directly interacting with other classes).

If you want to go a little further with a slighly more advanced approach, you can also implement your Engine class as a singleton (there is a nice flash example here ).

Making your engine class singleton means that you make sure there will be only one instance of the engine class in your memory and there only will be an instance until a part of your application needs it. You can access all the properties of a Singleton in a static manor.

Accessing the player property would then come down to:

private var _playerCol:player = Engine.instance._player;

The advantage is that now you can access all the public functions and variables of your Engine class easily.

The singleton pattern is used in allot of Flash libraries and applications, so it could be worth the time to explore them a little.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM