2013-04-24 5 views
0

Я пытаюсь закодировать редактор уровня на основе плитки, в котором основной класс добавляет экземпляры класса Tile в виде дочерних элементов мувиклипа «плитки» при нажатии и перетаскивании мыши. Я могу добавить плитки в контейнер, и они отображаются на сцене, однако я не могу удалить какие-либо плитки, когда их стирание включено. Это дает мне следующую ошибкуОшибка 2025 при попытке удалитьChild, ребенок не содержится там, где он был добавлен?

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); 
     } 
    } 
} 

ответ

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; 
    } 
} 
2

Следующий код вызывает проблему, в основном вы звоните removeChild дважды для того же объекта.

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

Мне это известно. Я оставил его там, когда реплицировал ошибку, потому что удаление этой строки просто предотвращает показ ошибки, но вообще не удаляет Плитки. – Illogical

+0

Входит ли он в строку if и trace 'Contained'. Если это так, и ошибок нет, значит, он удаляет его из плит. Попробуйте отладить и посмотрите, действительно ли цель удалена из фрагментов. –

+0

Я несколько раз пробовал отладку. Он не отслеживает и ничего не удаляет. Как-то кажется, что flash добавляет ребенка к чему-то другому, а не к контейнеру «плитки». – Illogical

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); 
+0

Это не имеет смысла. У вас есть оба, завернутые в условное условие на тесты, если это ребенок. Какая строка получает ошибку? Я не вижу, как вы можете получить ошибку с этой проверкой. – prototypical

+0

Позвольте мне объяснить себя лучше: условная проверка не показывает ошибку, но она также не удаляет дочерний объект. Это похоже на то, что вспышка вообще ничего не сделала, потому что, по-видимому, у ребенка нет родителя, к которому он был добавлен. – Illogical

+1

Возможно, вам стоит обновить сообщение с точной информацией и четкой/краткой информацией о том, что происходит. Сначала ... Пожалуйста, зайдите в настройки публикации и включите «разрешить отладку», чтобы они отображали номера строк для ошибок времени выполнения. Кроме того, вы должны ознакомиться с отладчиком, чтобы вы могли проверить значение своих переменных при прохождении кода, чтобы вы могли проверить, что они имеют значения, которые вы предполагаете. – prototypical

0

Сделать это легко на самостоятельно и создать класс для Tile с помощью метода remove. Что-то вроде этого:

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

Таким образом, вы можете просто сделать:

tile.remove();