【问题标题】:Passing an object reference between classes AS3在类 AS3 之间传递对象引用
【发布时间】:2015-04-13 02:49:02
【问题描述】:

制作地图创建程序。 Field.as 实例化 _player。 Player.as 将Child _editorPanel 添加到父级。当我单击编辑器面板中的按钮时,EditorPanel.as 会实例化一个名为 tilepalette 的影片剪辑。 Tilepalette 包含我希望能够通过单击我想要的图块从中选择一个图块的所有图块集。

Field.as:

package  {

    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.FrameLabel;
    import flash.display.DisplayObjectContainer;
    import flash.geom.Rectangle;

    public class Field extends MovieClip{

        private var player:Player;
        private var sampleTile:Tile = new Tile();
        private var _tilePalette:TilePalette;
        private var _paletteArray:Array = [];

        public function Field() 
        {
            player = new Player();
            player.x = 0;
            player.y = 0;
            addChild(player);

            GetSampleTiles();
        }

        private function GetSampleTiles()
        {
            for (var i:int = 1; i <= sampleTile.totalFrames; i++)
            {
                var tileObj:Object = new Object();

                sampleTile.gotoAndStop(i);

                var graphicData:BitmapData = new BitmapData(32,32);
                graphicData.draw(sampleTile);

                tileObj.Name = sampleTile.currentFrameLabel;
                tileObj.Graphic = graphicData;
                tileObj.Frame = sampleTile.currentFrame;

                Engine._tilesData.push(tileObj);
            }
        }
    }
}

Player.as:

package  {

    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.display.BitmapData;
    import flash.display.Bitmap;


    public class Player extends MovieClip 
    {
        private var _inp:Input = new Input();
        private var _playerXindex:int = 0;
        private var _playerYindex:int = 0;
        private var _heldTile:Object;
        private var _editorPanel:EditorPanel;

        public function Player() 
        {
            addChild(_inp);
            addEventListener(Event.ENTER_FRAME, HandleKeys);

            _heldTile = new Object();
        }

        private function HandleKeys(e:Event)
        {
            _playerXindex = x/32;
            _playerYindex = y/32;

            if(_inp.keyUp)
            {
                y -= 32;
            }
            if(_inp.keyDown)
            {
                y += 32;
            }
            if(_inp.keyLeft)
            {
                x -= 32;
            }
            if(_inp.keyRight)
            {
                x += 32;
            }
            if(_inp.keySpace)
            {
                try{DrawATile(_heldTile);}
                catch(err:Error){trace("Bad or no graphic. Using this instead.");}
                finally{DrawATile(Engine._tilesData[0]);}
            }
            if(_inp.keyA)
            {
                trace(Engine.tileObjIndex[_playerYindex][_playerXindex].Name);
            }
            if(_inp.keyB)
            {
                BuildStarterIndex();
                SetHeldTile(Engine._tilesData[0]);
            }
        }

        private function DrawATile(tileToDraw:Object)
        {
            if (Engine.tileObjIndex[_playerYindex][_playerXindex].Name.indexOf("Placeholder") >= 0)
            {
                trace("set");
                var graphicData:BitmapData = new BitmapData(32,32);
                graphicData.draw(tileToDraw.Graphic);

                Engine.tileObjIndex[_playerYindex][_playerXindex].Name = tileToDraw.Name;
                Engine.tileObjIndex[_playerYindex][_playerXindex].Graphic = tileToDraw.Graphic;

                var newTile:Bitmap = new Bitmap(tileToDraw.Graphic);
                newTile.x = x;
                newTile.y = y;
                parent.addChild(newTile);
            }
        }

        private function BuildStarterIndex()
        {
            _editorPanel = new EditorPanel();
            _editorPanel.x = 1;
            _editorPanel.y = 544;
            parent.addChild(_editorPanel);

            for (var i:int = 0; i < 20; i++)
            {
                Engine.tileObjIndex[i] = [];

                for (var u:int = 0; u < 20; u++)
                {
                    var tileObj:Object = new Object();

                    var graphicData:BitmapData = new BitmapData(32,32);
                    graphicData.draw(Engine._tilesData[0].Graphic);

                    tileObj.Name = "Placeholder" + "["+i+"]"+"["+u+"]";
                    tileObj.Graphic = graphicData;
                    tileObj.Frame = 0;

                    Engine.tileObjIndex[i].push(tileObj);
                }
            }
        }

        private function SetHeldTile(tiletoset:Object)
        {
            _heldTile.Name = tiletoset.Name;
            _heldTile.Graphic = tiletoset.Graphic;
            _heldTile.Frame = tiletoset.Frame;

            _editorPanel.tileName.text = _heldTile.Name;
            _editorPanel.tileFrame.text = _heldTile.Frame;

            var heldTile:Bitmap = new Bitmap(_heldTile.Graphic);
            heldTile.x = 30;
            heldTile.y = 31;
            _editorPanel.addChild(heldTile);
        }
    }
}

EditorPanel.as:

package  {

    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.display.Bitmap;
    import flash.events.Event;

    public class EditorPanel extends MovieClip
    {
        public var _tilePalette:TilePalette;
        private var _pArray:Array = [];
        private var _mouseXi:int;
        private var _mouseYi:int;
        public var _tileGrabbed:Object;

        public function EditorPanel() 
        {
            btnpalette.addEventListener(MouseEvent.CLICK, BuildPalette);
        }

        private function UpdateMouse(e:Event)
        {
            _mouseXi = Math.floor(_tilePalette.mouseX/32);
            _mouseYi = Math.floor(_tilePalette.mouseY/32);
        }

        private function BuildPalette(e:MouseEvent)
        {
            _tilePalette = new TilePalette();
            _tilePalette.x = mouseX;
            _tilePalette.y = mouseY-256;
            addChild(_tilePalette);
            var counter:int = 1;

            for (var i:int = 0; i < 8; i++)
            {
                _pArray[i] = [];
                for(var u:int = 0; u < 8; u++)
                {
                    if(counter >= Engine._tilesData.length)
                    {
                        counter = 1;
                    }
                    var b:Bitmap = new Bitmap(Engine._tilesData[counter].Graphic);
                    b.x = 32 * u;
                    b.y = 32 * i;
                    _tilePalette.addChild(b);

                    _pArray[i].push(Engine._tilesData[counter]);
                    counter++;
                }
            }
            _tilePalette.addEventListener(MouseEvent.MOUSE_MOVE, UpdateMouse);
            _tilePalette.addEventListener(MouseEvent.CLICK, GrabATile);
        }

        private function GrabATile(e:MouseEvent)
        {
            return _pArray[_mouseXi][_mouseYi];
        }
    }
}

问题是当我做 GrabATile 时,我不知道如何处理返回的 Object 引用。我想在 Player 函数 SetHeldTile 中使用该对象。

【问题讨论】:

  • 帮我理解这里发生了什么,玩家有能力抢一块瓷砖,对吗?
  • 嗯,我有点计划在未来,但现在我只想能够从 tilePalette 中单击我想要的图块。
  • 播放时,您可以使用箭头键移动播放器并使用空格键放下瓷砖图形。当你按下 b 时,我让它设置了一个默认的 _heldTile。
  • 你没有写正确的代码?因为代码已经在一个地方完成了您要求的操作,因此除非您一开始没有编写该代码,否则您不知道该怎么做是没有意义的。
  • 我确实写了代码。我半明白了。它返回对象引用 (_pArray[_mouseXi][_mouseYi]) 但它返回到哪里?如何让 SetHeldTile 函数使用该对象引用作为其参数??

标签: actionscript-3


【解决方案1】:

所以这将使它工作,但我建议稍微重构一下该代码。添加向他们的父母添加东西的孩子不是最好的设计......那里还有循环赛的东西,编辑器选择瓷砖,但是玩家在被告知后将像tileName这样的东西设置回编辑器新瓷砖。这应该发生在发生平铺选择等的编辑器中。

也就是说,根据您的流程,以下是如何使其工作:

EditorPanel 已经有一个属性 _tileGrabbed。所以在你的 GrabATile() 方法中只需设置

_tileGrabbed = _pArray[_mouseXi][_mouseYi];

然后在你的 setHeldTile() 方法中......简单地说

_heldTile = _editorPanel._tileGrabbed.  

现在,如果您需要 GrabATile() 来触发 setHeldTile(),最好的处理方法是使用事件。

// in EditorPanel

private function GrabATile(e:MouseEvent){
    _tileGrabbed =  _pArray[_mouseXi][_mouseYi];
    dispatchEvent(new Event("tileChanged"));
}

// in Player

private function BuildStarterIndex(){
    _editorPanel = new EditorPanel();
    _editorPanel.addEventListener("tileChanged", setHeldTile);
    // ... rest of code
}

private function SetHeldTile(event:Event){
    _heldTile = _editorPanel._tileGrabbed;
    // ... rest of code
}

【讨论】:

  • 非常感谢。我在这方面玩了一段时间的自定义事件,但无法让它发挥作用。我对有这么多课程有点陌生,所以我正在经历一些成长的痛苦。我已经开始重新写它了……就像第四次。哈哈。再次感谢
  • 我阅读和阅读并查看了许多示例,但对我来说仍然没有多大意义。我知道子类应该“改变他们自己的尿布”并且我应该避免循环依赖等等,但是当我去写它时,似乎我不禁把它设计得很糟糕。动物的例子对我来说完全有意义,但它们非常直截了当。当谈到编写更多抽象类时,我感到迷茫。
  • 我明白了!它需要一段时间才能成为设计代码的“第二天性”。我能给你的最好建议是首先考虑单一责任……这意味着一个班级应该做/代表一件事,而且只代表那件事。在编写代码之前“思考”代码很有帮助。把它写在纸上,隔离所有需要存在的不同事物以及所有需要发生的不同动作……开始将它们全部分离到执行这些事情的类中。你还应该看看 SOLID,en.wikipedia.org/wiki/SOLID_(object-oriented_design)
  • 至于循环引用......想想这样的事情:玩家真的需要一个“heldTile”属性吗?牌与玩家无关。它们是两个独立的不相关的“事物”。创建一个具有“activeTile”属性的模型类会是更好的设计,并且每当玩家需要了解它,或者例如查看玩家和瓷砖是否彼此靠近的代码时,该代码可以只看模型.activeTile。搜索一下 MVC(模型视图控制器)以及类的职责是如何划分的!你会得到你的“啊哈”时刻......承诺
  • 感谢您的鼓励。我觉得我一直在问愚蠢的问题。哈哈。我想我开始明白了。这些确实很有帮助:stackoverflow.com/questions/6293429/…actionscript.org/resources/articles/698/4/… 我编写了一个名为 HandleTiles 的类,它完成了瓷砖需要做的所有事情。我还编写了一个名为 HandleGraphics 的类,它目前只有一个功能(DrawGrid),效果很好。现在,HandleTile 或 HandleGraphics 是否应该具有 DrawATile 函数?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 2013-02-09
  • 1970-01-01
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多