как удалить дочерний объект с помощью removeChild()?

Я пытаюсь создать собственный анимированный шутер из этого руководства: http://flashadvanced.com/creating-small-shooting-game-as3/

Под кастомом я подразумеваю кастомизированный, т.е. свой собственный вариант.

В его скрипте действия есть прослушиватель событий таймера с функцией: timerHandler() Эта функция добавляет и удаляет дочерние «звездные» объекты на сцене (в которые пользователь должен стрелять):

if(starAdded){
removeChild(star);
}

и :

addChild(star);

Код работает отлично, но возникает ошибка на сцене 2.

Код отлично работает, и я даже добавил некоторый код во время обучения через google и stackflow в этот flash-файл. Я также добавил к нему Сцену 2, и она вызывалась через 9 секунд времени фильма. Но когда он переходит к Сцене 2, он по-прежнему отображает звездные объекты, и мне не удалось удалить эти «звездные» объекты из Сцены 2.

Вот код, который я добавил:

СЦЕНА 1:

var my_timer = new Timer(5000,0); //in milliseconds
my_timer.addEventListener(TimerEvent.TIMER, catchTimer);
my_timer.start();


var myInt:int = getTimer() * 0.001;
var startTime:int = getTimer();
var currentTime:int = getTimer();
var timeRunning:int = (currentTime - startTime) * 0.001; // this is how many seconds the game has been running.
demo_txt.text = timeRunning.toString();

function catchTimer(e:TimerEvent)
{
    gotoAndPlay(1, "Scene 2");
}

СЦЕНА 2:

addEventListener(Event.ENTER_FRAME,myFunction);
function myFunction(event:Event) {
    timer.stop();
    timer.removeEventListener(TimerEvent.TIMER, timerHandler);
    stage.removeChild(star);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, cursorMoveHandler);
    my_timer.stop(); // you might need to cast this into Timer object
    my_timer.removeEventListener(TimerEvent.TIMER, catchTimer);
    Mouse.show();
}
stop();

=====================================================

Я новичок в as3 и только что создал учетную запись на StackOverflow... хотя я уже давно знаю и читал на ней множество кодов.

Вот отредактированный новый полный код:

//importing tween classes
import fl.transitions.easing.*;
import fl.transitions.Tween;

//hiding the cursor
Mouse.hide();

//creating a new Star instance
var star:Star = new Star();
var game:Game = new Game();
//creating the timer
var timer:Timer = new Timer(1000);
//we create variables for random X and Y positions
var randomX:Number;
var randomY:Number;
var t:int = 0;
//variable for the alpha tween effect
var tween:Tween;
//we check if a star instance is already added to the stage
var starAdded:Boolean = false;
//we count the points
var points:int = 0;

//adding event handler on mouse move
stage.addEventListener(MouseEvent.MOUSE_MOVE, cursorMoveHandler);
//adding event handler to the timer
timer.addEventListener(TimerEvent.TIMER, timerHandler);
//starting the timer
timer.start();
addChild(game);
function cursorMoveHandler(e:Event):void{
    //sight position matches the mouse position
    game.Sight.x = mouseX;
    game.Sight.y = mouseY;
}

function timerHandler(e:TimerEvent):void{
    //first we need to remove the star from the stage if already added
    if(starAdded){
        removeChild(star);
    }

    //positioning the star on a random position
    randomX = Math.random()*500;
    randomY = Math.random()*300;
    star.x = randomX;
    star.y = randomY;
    //adding the star to the stage
    addChild(star);
    //changing our boolean value to true
    starAdded = true;
    //adding a mouse click handler to the star
    star.addEventListener(MouseEvent.CLICK, clickHandler);
    //animating the star's appearance
    tween = new Tween(star, "alpha", Strong.easeOut, 0, 1, 3, true);
t++;
if(t>=5) {
    gotoAndPlay(5);
}
}

function clickHandler(e:Event):void{
    //when we click/shoot a star we increment the points
    points ++;
    //showing the result in the text field
    points_txt.text = points.toString();
}

И на кадре 5:

//timer.stop();
    //timer.removeEventListener(TimerEvent.TIMER, timerHandler);
    // uncomment lines above if "timer" is something you've made
    stage.removeChild(star);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, cursorMoveHandler);
    timer.stop(); // you might need to cast this into Timer object
    timer.removeEventListener(TimerEvent.TIMER, timerHandler);
    Mouse.show();
    stop();

Теперь в этом новом файле .fla нет Сцены 2... Вот скриншот свойства библиотеки моего файла прошивки...: http://i.imgur.com/d2cPyOx.jpg


person mk117    schedule 13.05.2013    source источник


Ответы (2)


Вам лучше вообще отказаться от сцен, они в значительной степени устарели в AS3. Вместо этого используйте объект Game, который содержит все курсоры, звезды и другие элементы внутри игры, и вместо gotoAndPlay() используйте removeChild(game); addChild(scoreboard);, где «табло» — это еще один контейнерный класс, который будет отображать ваш счет.

Что касается вашего кода, вы перестаете иметь действительный дескриптор stage, который на самом деле содержит ваш star, потому что вы изменили сцену. Так что сделайте все это перед вызовом gotoAndPlay() в вашей функции catchTimer.

function catchTimer(e:TimerEvent)
{
    //timer.stop();
    //timer.removeEventListener(TimerEvent.TIMER, timerHandler);
    // uncomment lines above if "timer" is something you've made
    stage.removeChild(star);
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, cursorMoveHandler);
    my_timer.stop(); // you might need to cast this into Timer object
    my_timer.removeEventListener(TimerEvent.TIMER, catchTimer);
    Mouse.show();
    gotoAndPlay(1, "Scene 2");
}

А код Сцены 2 будет состоять из одного stop() - пока вы туда что-то не добавите. Кроме того, не должно быть прослушивателей событий, особенно enter-frame, без кода для удаления этого прослушивателя! Вы добавляете прослушиватель ввода кадра в сцену 2 и никогда не удаляете его, в то время как вам нужно, чтобы этот код запускался только один раз.

person Vesper    schedule 13.05.2013
comment
Я не знаю/не помню, как работать с классами и объектами. Если я создам и конвертирую курсор, звездочку в мувиклипы, а затем сгруппирую их в другой муви-клип, игру... то как я смогу добавлять новые звёздочки на сцену?. var star:Star = новая звезда(); //добавляет новую объектную переменную Идентификатор формы звезды в библиотеку. Как мне вызвать addChild(star); если все содержимое завернуто в игровой ролик? Должен ли я их группировать в любом случае? А потом связать game.star с ac3 через идентификатор? Да, тогда как мне объявить звездную переменную? var star:Star = новая звезда(); ?? - person mk117; 14.05.2013
comment
Что ж, я сгруппировал мувиклипы звезды и курсора (прицела) в другой мувиклип Game идентификатора, и вот как я изменил код, который снова не работал .. var game:Game = new Game (); game.Sight.x = мышьX; удалитьРебенок(игра.Звезда); game.Star.x = случайныйX; game.addEventListener...tween = new Tween(game.Star, alpha,... только что скопировал требуемый код для, остальная часть кода похожа только на ссылку на обучающую страницу с игрой (как показано в вопрос этой страницы) - person mk117; 14.05.2013
comment
Пожалуйста, добавьте к вопросу отредактированный код (отредактируйте вопрос). Возможно, есть опечатка, которая вызывает ошибочное поведение. - person Vesper; 14.05.2013
comment
Видите ли, объект star по-прежнему имеет stage в качестве родителя, поэтому звезда не будет удалена с экрана, если вы удалите только game. Кроме того, теперь к вашему star добавляется прослушиватель кликов каждый тик таймера — разве это не неправильно, поскольку вы создаете new Star() только один раз? Вы создаете, добавляете и пусть это будет. Еще одна придирка - если ваш игрок будет лихорадочно щелкать по звезде, он получит много очков, я думаю, звезда должна перемещаться каждый раз, когда по ней щелкают. - person Vesper; 14.05.2013
comment
Хорошо.. так что я должен полностью удалить игровой объект? Чтобы остались только Звезда и указатель/прицел? При этом он вернется к исходному рабочему коду с единственной проблемой, что я не могу закончить игру ... для которой вы предложили перемещаться по кликам. Итак, какую часть кода я должен перенести в clickHandler? - person mk117; 14.05.2013
comment
У вас есть код в обработчике таймера, который перемещает звезду, эту часть следует переместить в обработчик кликов. И да, если вы используете фреймы для отображения эндшпиля, вам не нужны Game вещи. - person Vesper; 14.05.2013
comment
Я добавил этот код в обработчик кликов, и теперь он намного лучше! Спасибо! :D if(starAdded) { removeChild(star); starAdded = false; } - person mk117; 14.05.2013

Используйте getChildAt.


    function catchTimer(e:TimerEvent)
    {
        var childCount:int = this.numChildren - 1;
        var i:int;
        var tempObj:DisplayObject;
        for (i = 0; i < childCount; i++)
        {
        tempObj = this.getChildAt(i);
        this.removeChild(tempObj);
        }
        gotoAndPlay(1, "Scene 2");
    }

Это удалит всех дочерних элементов, добавленных вами в сцену 1, прежде чем перейти к сцене 2.

person Fabrice Bacquart    schedule 14.05.2013
comment
Это успешно удалило звездный объект ... но не перешло к сцене 2 ... У меня был пустой экран без текста или чего-то еще, и даже курсор мыши не показывался! - person mk117; 14.05.2013