Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Проблема с Event (http://www.flasher.ru/forum/showthread.php?t=204470)

LIGHTHILL 31.10.2013 04:17

Проблема с Event
 
Пытаюсь сделать анимацию клика. Создал сам MovieClip (расширяющийся кружочек из точки клика).
Сначала добавлял один экземпляр и в случае клика в другом месте, не закончившаяся анимация исчезала и воспроизводилась заново в новом месте. Всё работало. Решил сделать, что бы при каждом новом клике создавался новый экземпляр не мешая окончиться предыдущему. Но столкнулся с проблемой, в случае с одним экземпляром, переменная которого объявлялась ещё в самом классе, я без проблем обращался к номеру кадра этого экземпляра, и когда он оканчивался, я удалял его. Сейчас каждый новый экземпляр создаётся в функции ивента клика мышкой по сцене. И я не пойму как правильно написать Слушатель ON_ENTER_FRAME для каждого экземпляра. Всё время ошибки, и currentFrame всегда 1.
Вот то, что сделано на текущий момент (не работает):
Код AS3:

package 
{
        import flash.display.MovieClip;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends MovieClip
        {
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        stage.addEventListener(MouseEvent.CLICK, onClick);
                }
 
                private function onClick(e:MouseEvent): void
                {
                        var circle:CircleAnimation = new CircleAnimation();
                        stage.addChild(circle);
                        circle.x = mouseX;
                        circle.y = mouseY;
                        circle.addEventListener(Event.ENTER_FRAME, onEnter);
                        circle.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
                }
 
                private function onEnter(e:Event): void
                {
                        if (this.currentFrame == this.totalFrames)
                        {
                                stage.removeChild(this);
                        }
                }
 
                private function onRemoved(e:Event): void
                {
                        this.removeEventListener(Event.ENTER_FRAME, onEnter);
                        this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
                }
 
        }
 
}


samana 31.10.2013 14:44

В методах onEnter и onRemoved, замените this на
Код AS3:

(e.currentTarget as MovieClip)

И не добавляйте объекты на stage. Вы ведь создаёте их в Main классе, вот в него и добавляйте.

Akopalipsis 31.10.2013 14:54

samana давно подметил, что Вы очень хорошо знаете тему анимация, по этому задам Вам вопрос - в программе ( фп ) всегда работает EnterFrame и запись
Код AS3:

circle.addEventListener(Event.ENTER_FRAME, onEnter);

говорит о том, что circle мы заставляем слушать этот EnterFrame. Но правильно ли создавать для каждого обьекта свой обработчик ENTER_FRAME ? Лучше ведь когда создан класс с энтерФрайм и обьекты добавлять в него?

caseyryan 31.10.2013 14:56

Цитата:

Но правильно ли создавать для каждого обьекта свой обработчик ENTER_FRAME ?
Не правильно. EnterFrame должен быть один на всю программу, в идеале. Чем больше таких слушателей, тем больше тормозов

samana 31.10.2013 14:59

Да, лучше все объекты запихнуть в массив, и в одном энтерФрейме через цикл изменять в них свойства.
А лучше вообще сделать один энтерФрейм для всего приложения.
caseyryan опередил)

LIGHTHILL 31.10.2013 15:03

Цитата:

Сообщение от samana (Сообщение 1150573)
И не добавляйте объекты на stage. Вы ведь создаёте их в Main классе, вот в него и добавляйте.

Вот это не очень понял
Код AS3:

package 
{
        import flash.display.MovieClip;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends MovieClip
        {
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        stage.addEventListener(MouseEvent.CLICK, onClick);
                }
 
                private function onClick(e:MouseEvent): void
                {
                        var circle:CircleAnimation = new CircleAnimation();
                        addChild(circle);
                        circle.x = mouseX;
                        circle.y = mouseY;
                        circle.addEventListener(Event.ENTER_FRAME, onEnter);
                        circle.addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
                }
 
                private function onEnter(e:Event): void
                {
                        if (e.target.currentFrame == e.target.totalFrames)
                        {
                                removeChild(MovieClip(e.target));
                        }
                }
 
                private function onRemoved(e:Event): void
                {
                        e.target.removeEventListener(Event.ENTER_FRAME, onEnter);
                        e.target.removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
                }
 
        }
 
}

Вот так всё работает, в таком случае я куда добавляю объекты?

samana 31.10.2013 15:04

Так вы добавляете в Main класс, всё верно.

Akopalipsis 31.10.2013 15:11

caseyryan Спасибо! Тогда такой вопрос - подписывая circle на ENTER_FRAME, мы передаём listener в EventDispatcher, где он помещается в массив и при каждом тике, вызываются все listeners из массива. Если сделать отдельный класс для ENTER_FRAME, то в моём понимании, это будет выглядеть так - создали экземпляр и чтобы подписаться на его тики, мы передаем в него ссылку на класс с методом, который должен вызываться каждый тик. Передав ссылку в класс ENTER_FRAME, она помещается в массив и каждый тик, этот массив перебирается циклом и вызывает нужный метод. Получается тоже самое.
По этому мне кажется, что я не понимаю, как сделать один класс с ENTER_FRAME. Где я ошибаюсь?

Добавлено через 5 минут
Цитата:

Вот это не очень понял
Вы просто запомните, что так делать нельзя.
Код AS3:

stage.addChild(circle);

А вот так можно.
Код AS3:

this.addChild(circle);

Код AS3:

addChild(circle);


LIGHTHILL 31.10.2013 15:22

И ещё вопрос, получается при каждом новом щелчке создаётся новый объект, как к этим объектам можно обратиться? Ведь их может быть бесконечно много. И как их можно сделать доступными для сборщика мусора, после удаления?

Добавлено через 10 минут
Сначала я сделал один экземпляр CircleAnimation в самом классе, всё отлично работало. Просто стало интересно как сделать так, что бы анимация не обрывалась при новом щелчке в другом месте. Может есть ещё какой-то менее ресурсозатратный способ?

Добавлено через 14 минут
А если я в самом классе CircleAnimation напишу, что бы он удалялся из родительского объекта после воспроизведения, будет лучше? Но, как я понимаю там опять же ENTER_FRAME нужно будет использовать.

samana 31.10.2013 15:38

Цитата:

Сообщение от Akopalipsis (Сообщение 1150579)
Тогда такой вопрос - подписывая circle на ENTER_FRAME, мы передаём listener в EventDispatcher, где он помещается в массив и при каждом тике, вызываются все listeners из массива. Если сделать отдельный класс для ENTER_FRAME, то в моём понимании, это будет выглядеть так - создали экземпляр и чтобы подписаться на его тики, мы передаем в него ссылку на класс с методом, который должен вызываться каждый тик. Передав ссылку в класс ENTER_FRAME, она помещается в массив и каждый тик, этот массив перебирается циклом и вызывает нужный метод. Получается тоже самое.
По этому мне кажется, что я не понимаю, как сделать один класс с ENTER_FRAME. Где я ошибаюсь?

Я не знаю, как там во флеше внутри реализована система передачи событий, но то, что одним энтерФрейм-ом быстрее перебрать в массиве все объекты, действительно лучше, чем на каждый объект вешать отдельный энетерФрейм.
Я сделал тест - подписал сто тысяч объектов, каждый на свой ентерФрейм, результат - 5 fps. А когда в цикле пробегал по этим ста тысячам - 16 fps.

Добавлено через 29 минут
LIGHTHILL Не забудьте, когда удаляете экземпляр CircleAnimation, остановить его внутренний енретФрейм. А то ещё некоторое время будет висеть в памяти, пока сборщик мусора не проснётся.
Код AS3:

circle.stop()



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

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