Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Проблема с доступом к объекту при вызове removeChild (http://www.flasher.ru/forum/showthread.php?t=211768)

EndoCrinologist 04.11.2015 01:19

Проблема с доступом к объекту при вызове removeChild
 
Изучаю AS3. Пытаюсь перевести игру Atary Asteroids из AS2 на AS3.
Вот класс Asteroids:
Код AS3:

package 
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.utils.setTimeout;
        /**
        * ...
        * @author Volodin Alexandr Sergeevich
        */

        public class Asteroid extends Sprite
        {
                public static var THIS:Asteroid = null;
 
                public var velX:Number = Math.random() * 6 - 3;
                public var velY:Number = Math.random() * 6 - 3;
                public var rotSpeed:Number = Math.random() * 3;
                public var rotDir:Number = chooseDir();
                public var frame:Number = 0;
 
                public function Asteroid()
                {
                        graphics.beginFill(0xabc098);
                        graphics.lineStyle(1);
                        graphics.moveTo(-50, -50);
                        graphics.lineTo(50, -50);
                        graphics.lineTo(50, 50);
                        graphics.lineTo(-50, 50);
                        graphics.lineTo(-50, -50);
                        graphics.endFill();
 
                        addEventListener(Event.ENTER_FRAME, onAstMove);
                }
 
                private function onAstMove(e:Event = null):void
                {
                        this.x += this.velX;
                        this.y += this.velY;
 
                        if (this.x > Main.THIS.StageX + this.width) this.x = 0 - this.width;
                        if (this.y > Main.THIS.StageY + this.width) this.y = 0 - this.width;
                        if (this.x < 0 - this.width) this.x = Main.THIS.StageX + this.width;
                        if (this.y < 0 - this.width) this.y = Main.THIS.StageY + this.width;
 
                        this.rotation += this.rotDir * this.rotSpeed;
 
                        frame++;
 
                        if (frame % 10 == 0)
                        {
                                //Main.THIS.graphics.beginFill(0x00ffaa);
                                //Main.THIS.graphics.drawCircle(this.x, this.y, 3);
                                //Main.THIS.graphics.endFill();
                        }
 
                        if (this.hitTestPoint(Main.THIS.ship.x, Main.THIS.ship.y, true))
                        {
                                Main.THIS.isDead = true;
                                Main.THIS.shipDestroy();
                        }
                }
 
                private function chooseDir():Number
                {
                        var rnd:Number = Math.random();
                        if (rnd > 0.5){return 1;} else return -1;
                }
 
        }
 
}

Вот класс Main:
Код AS3:

package
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.KeyboardEvent;
 
 
        /**
        * ...
        * @author Volodin Alexandr Sergeevich
        */

        public class Main extends Sprite
        {
                public static var THIS:Main = null;
 
                public var rotate:Number = 0;
                public var thrust:Number = 0;
 
                public var StageX:Number = 800;
                public var StageY:Number = 600;
 
                public var frame:Number = 0;
 
                public var isDead:Boolean = false;
 
                public function Main()
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                public var ship:Ship = new Ship();
                private var ast_sprite:Sprite = new Sprite();
 
                private function init(e:Event = null):void
                {
                        THIS = this;
 
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        // entry point
 
                        ship.x = StageX / 2;
                        ship.y = StageY / 2;
 
                        addChild(ship);
 
                        stage.addEventListener(KeyboardEvent.KEY_DOWN, shipControl);
                        stage.addEventListener(KeyboardEvent.KEY_UP, shipDecontrol);
                        ship.addEventListener(Event.ENTER_FRAME, onShipMove);
 
                        addChild(ast_sprite);
 
                        frame++;
 
                        for (var i:int = 0; i < 5; i++ )
                        {
                                var ast:Asteroid = new Asteroid();
                                addChild(ast);
                        }
 
                }
 
                private function shipDecontrol(e:KeyboardEvent):void
                {
                        rotate = 0;
                        thrust = 0;
                }
 
                private function shipControl(e:KeyboardEvent):void
                {
                        switch(e.keyCode)
                        {
                                case 37:
                                        rotate = -1;
                                        break;
                                case 38:
                                        thrust = 0.3;
                                        break;
                                case 39:
                                        rotate = 1;
                                        break;
                                case 40:
                                        thrust = -0.3;
                                        break;
                        }
                }
 
                private function onShipMove(e:Event = null):void
                {
                        if (rotate) ship.rotation += rotate * 5;
                        if (Math.abs(thrust) > 0)
                        {
                                var rad:Number = ship.rotation * Math.PI / 180;
                                ship.thrustX = Math.cos(rad) * thrust;
                                ship.thrustY = Math.sin(rad) * thrust;
 
                                ship.velX += ship.thrustX;
                                ship.velY += ship.thrustY;
                        }
 
                        ship.x += ship.velX;
                        ship.y += ship.velY;
 
                        if (ship.x > StageX + ship.width) ship.x = 0 - ship.width;
                        if (ship.x < 0 - ship.width) ship.x = StageX + ship.width;
 
                        if (ship.y > StageY + ship.width) ship.y = 0 - ship.width;
                        if (ship.y < 0 - ship.width) ship.y = StageY + ship.width;
                }
 
                public function shipDestroy()
                {
                        removeChild(ship);
                }
 
        }
 
}

Вот класс Ship:
Код AS3:

package 
{
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.KeyboardEvent;
 
        /**
        * ...
        * @author Volodin Alexandr Sergeevich
        */

        public class Ship extends Sprite
        {
                //private var spr : Sprite = new Sprite();
 
                public var velX : Number = 0;
                public var velY : Number = 0;
                public var thrustX : Number = 0;
                public var thrustY : Number = 0;
 
                public function Ship()
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, onStageShip);
                }
 
                private function onStageShip(e:Event = null):void
                {
                        /*spr.graphics.beginFill(0x00ff00);
                        spr.graphics.lineStyle(1);
                        spr.graphics.moveTo(-20,-20);
                        spr.graphics.lineTo(20, 0);
                        spr.graphics.lineTo(-20, 20);
                        spr.graphics.endFill();*/

 
                        graphics.beginFill(0x00ff00);
                        graphics.lineStyle(1);
                        graphics.moveTo(-20,-20);
                        graphics.lineTo(20, 0);
                        graphics.lineTo(-20, 20);
                        graphics.endFill();
 
                        //addChild(spr);
                }
 
                public function shipDead():void
                {
                        removeChild(this);
                }
        }
 
}

При соприкосновении астероида и корабля возникает такая ошибка:
Цитата:

ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller.
at flash.display::DisplayObjectContainer/removeChild()
at Main/shipDestroy()[Main.as:113]
at Asteroid/onAstMove()[Asteroid.as:58]
Что не так?

alexandrratush 04.11.2015 10:52

Может быть в этом проблема: The supplied DisplayObject must be a child of the caller.

caseyryan 04.11.2015 11:30

Код AS3:

removeChild(this);

Эта запись эквивалентна такой:
Код AS3:

this.removeChild(this);

Не может объект удалить самого себя из себя

EndoCrinologist 04.11.2015 12:08

Я понял, что что-то не так с родителями/детьми. Я также пробовал способ удаления самой ship, когда в Main создавал функцию, удаляющую ship, но она вызывала такую же ошибку..
Класс Main:
Код AS3:

public function shipDestroy()
                {
                        removeChild(ship);
                }

Вызов из Asteroids:
Код AS3:

if (this.hitTestPoint(Main.THIS.ship.x, Main.THIS.ship.y, true))
                        {
                                Main.THIS.isDead = true;
                                Main.THIS.shipDestroy();
                        }

Или, я так понимаю, он всё равно из себя не сможет вызвать какую-то стороннюю функцию для удаления себя?

caseyryan 04.11.2015 19:22

Не буду говорить на сколько сам код плохо написан, для новичка простительно. Поэтому сразу скажу по делу. Чтобы он мог удалиться из дисплей листа сам, можно сделать так:
Код AS3:

if (parent) parent.removeChild(this);

Собственно делаем проверку на то есть ли у него родитель, и если есть, удаляем. Проверка нужна, чтобы он не падал с ошибкой, если он не находится в дисплей листе во время попытки удаления.

п.с. Таким образом объект никуда не удаляется, и продолжает и висеть в памяти и жрать ресурсы процессора (пока на него сохраняются ссылки). Он просто перестает отображаться


Часовой пояс GMT +4, время: 11:09.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.