0

我正在尝试编写一个基于 tile 的级别编辑器,其中 Main 类在单击/拖动鼠标时将 Tile 类实例添加为“tiles”movieclip 的子级。我可以将图块添加到容器中,并且它们会显示在舞台上,但是在启用擦除它们时我无法删除任何图块。它给了我以下错误

Error #2025: The supplied DisplayObject must be a child of the caller.
    at flash.display::DisplayObjectContainer/removeChild()
        at Main/Draw()
        at Main/::Go()

此外,当我检查瓷砖是否在瓷砖容器内时,它告诉我父级为空。

所以,有点帮助?我尝试检查具有类似问题的其他问题,但似乎没有一个与我的问题相近。

package {
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display.StageScaleMode;
    import flash.display.StageAlign;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.KeyboardEvent;
    //import flash.events.TimerEvent.updateAfterEvent;

    public class Main extends MovieClip {

        //containers
        var lines:Sprite = new Sprite();
        var tiles:Sprite = new Sprite();

        // Grid data
        var tileW:int = 20;
        var tileH:int = 20;
        var gridW:int = 20;//(inputWidth);
        var gridH:int = 20;//(inputHeight);
        var gridX:int = 50;
        var grixY:int = 50;
        var level:Array;

        //Drawing variables
        var go:Boolean = false;
        var erase:Boolean = false;

        var default_tile:int = 1;
        var type:int;

        var rect:Object = {x:100, y:50, width:(gridW * tileW)/100, height:(gridH * tileH)/100};

        //menus
        var sizeMenu:SizeMenu = new SizeMenu();

        var current:Tile = new Tile();

        public function Main():void {

            //Flash alignment and resizing
            stage.scaleMode=StageScaleMode.NO_SCALE;
            stage.align=StageAlign.TOP_LEFT;

            stage.addChild(lines);
            lines.x = rect.x;
            lines.y = rect.y;

            stage.addChild(tiles);
            tiles.x = rect.x;
            tiles.y = rect.y;

            stage.addChild(sizeMenu);

            stage.addChild(current);
            current.x = 50;
            current.gotoAndStop(default_tile);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, Go);
            stage.addEventListener(MouseEvent.MOUSE_UP, Go);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, Go);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, ToggleErase);
            stage.addEventListener(KeyboardEvent.KEY_UP, ToggleErase);

            Setup();

        }
        //Draws grid lines
        private function Setup():void {
            trace("Drawing Grid...");
            // create an empty array
            level = new Array(gridH);
            for (var i=0; i < gridW; i++) {
                level[i] = new Array(gridW);
            }

            // attach lines to create a grid
            for (var k=0; k <= gridH; k++) {
                var line = new Line();
                line.name = "line"+k;
                line.scaleX = rect.width;
                line.y = tileH * k;
                lines.addChild(line);

                for (var j=0; j <= gridW; j++) {
                    line = new Line();
                    line.name = "line"+j+"_"+k;
                    line.scaleX = rect.height;
                    line.x = tileW * j;
                    line.rotation = 90;
                    lines.addChild(line);                   
                }
            }
            type = default_tile;
            trace("Done drawing grid!");
        }
        //Decided if drawing is possible
        private function Go(e:MouseEvent):void {
            if (e.type == "mouseDown") {
                go = true;
                Draw(e);
            }
            if (e.type == "mouseUp") {
                go = false;
            }
            if (e.type == "mouseMove") {
                if (go) {
                    Draw(e);
                }
                //e.updateAfterEvent();
            }
        }
        //Toggles erase
        private function ToggleErase(e:KeyboardEvent):void{
            if (e.shiftKey){
                erase = true;
            }
            if (e.type == "keyUp"){
                erase = false;
            }
        }


        // attaches the tiles when drawn on the grid
        public function Draw(e:MouseEvent) {
            var x = mouseX;
            var y = mouseY;
            var cx = Math.floor((x - rect.x) / tileW);
            var cy = Math.floor((y - rect.y) / tileH);



            if (cx >= 0 && cx < gridW && cy >= 0 && cy < gridH) {
                var target = e.currentTarget;
                if (!erase) {
                    if (tiles.contains(target)){
                        trace("Contained!");
                        tiles.removeChild(target);
                    }

                    var tile = new Tile();
                    tiles.addChild(tile);
                    tile.name = ("t_" + cy + "_" + cx);
                    tile.x = (tileW * cx);
                    tile.y = (tileH * cy);
                    tile.gotoAndStop(type);
                    level[cy][cx] = type;

                } else {
                    if (tiles.contains(target)){
                        trace("Contained!");
                        tiles.removeChild(target);
                    }

                    level[cy][cx] = default_tile - 1;
                }
            }
        }
        //Cleans the grid and redraws it
        private function ResetGrid():void {
            level = null;

            //Delete tiles
            while (tiles.numChildren) {
                tiles.removeChildAt(0);
            }
            //Delete lines 
            while (lines.numChildren) {
                lines.removeChildAt(0);
            }
            gridW=20;
            gridH=20;
            rect.width = (gridW * tileW)/100;
            rect.height = (gridH * tileH)/100;
        }
        // updates the current-clip
        private function update() {
            current.gotoAndStop(type);
        }
    }
}
4

4 回答 4

2

下面的代码导致了这个问题,基本上你removeChild为同一个对象调用了两次。

 if (tiles.contains(target)){
     trace("Contained!");
     tiles.removeChild(target);
 }
 tiles.removeChild(target);
于 2013-04-24T03:18:59.677 回答
0

在您的代码中,我注意到您可以删除磁贴,然后在此块的末尾再次尝试将其删除:

        if (!erase) {
            if (tiles.contains(target)){
                trace("Contained!");
                tiles.removeChild(target);
            }

            var tile = new Tile();
            tiles.addChild(tile);
            tile.name = ("t_" + cy + "_" + cx);
            tile.x = (tileW * cx);
            tile.y = (tileH * cy);
            tile.gotoAndStop(type);
            level[cy][cx] = type;

        } else {
            if (tiles.contains(target)){
                trace("Contained!");
                tiles.removeChild(target);
            }
            // this is going to throw an error
            tiles.removeChild(target);
于 2013-04-24T03:20:48.703 回答
0

让自己轻松一点,并Tile使用remove方法创建一个类。像这样的东西:

class Tile extends Sprite
{
    public function remove():void
    {
        if(parent) parent.removeChild(this);
    }
}

这样,您可以简单地执行以下操作:

tile.remove();
于 2013-04-24T06:36:16.620 回答
0

我已经解决了我的问题!所有瓦片实例在添加时都会根据它们在网格上的位置来命名。我没有将鼠标指向的对象作为目标,而是使用 getChildByName(); 搜索是否已经存在具有特定名称的对象,如果存在则将其删除。

if (cx >= 0 && cx < gridW && cy >= 0 && cy < gridH) {
    var target = tiles.getChildByName("t_" + cy + "_" + cx);

    if (!erase) {
        if (target){
            tiles.removeChild(target);
        }
        var tile = new Tile();
        tiles.addChild(tile);
        tile.name = ("t_" + cy + "_" + cx);
        tile.x = (tileW * cx);
        tile.y = (tileH * cy);
        tile.gotoAndStop(type);
        level[cy][cx] = type;
    } else {
        if (target){
            tiles.removeChild(target);
        }
        level[cy][cx] = default_tile - 1;
    }
}
于 2013-04-24T21:07:33.643 回答