Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как объяснить двойное срабатывание события (MouseEvent) ? (http://www.flasher.ru/forum/showthread.php?t=205104)

zCHESNOKz 18.11.2013 21:12

Как объяснить двойное срабатывание события (MouseEvent) ?
 
Есть главный класс, который отвечает за добавление и удаление дополнительных классов, таких как класс реализацией процесса игры, и класс с выбором уровней. Все просто, но есть одна проблема.

В выборе уровня кликаю по символу (в котором же присобачен слушатель MouseEvent.MOUSE_CLICK, потом этот символ диспатчит событие "CLICK_ME") а в классе выбора уровня его слушатель, который удаляет класс с выбором уровня и добавляет класс с самой игрой , после нажатия и перехода на класс с игрой , слушатели нажатия клавиш перестают отвечать, для этого нужно кликнуть по экрану , в итоге флэха отвечает на нажатия клавиш и все работает хорошо, перейдя в выбор уровней, а потом в игру, снова нужно кликнуть по экрану.

Почему так происходит? В чем проблема? При этом если в символе событие MouseEvent.MOUSE_WHEEL, то в игре также нужно поводить мышкой чтобы заработало.

НО если я при переходе в саму игру НЕ УДАЛЯЮ класс с выбором уровней, то все работает нормально. Почему, что меняется в этот раз меняется ? Не удаляются обработчик события клика?

Я уже думал, что это из-за параметра события useCapture , но нет.

Примеры:

Класс с выбором уровня:


Код AS3:

 public function addListener():void
                {
                        this.icon.buttom.addEventListener(MouseEvent.MOUSE_DOWN, onClick);
                }
 
                public function onClick(event:MouseEvent):void
                {
                        this.dispatchEvent( new Event("CLICK_ICON"));
                }

Главный класс, который отвечает за переход:

Код AS3:

public function Model(_stage:Stage)
                {
                        this._stage = _stage;
                        addMenu();
                }
 
                public function addMenu():void
                {
                        menu = new GameMenu(_stage);
                        this.addChild(menu);
 
                        menu.addListener();
                        menu.addEventListener("CLICK_ICON", onClickIcon);
                }
 
                public function delMenu():void
                {
                        removeChild(menu);
                }
 
                public function onClickIcon(event:Event):void
                {
                        this.removeEventListener("CLICK_ICON", onClickIcon);
                        trace ("onClickIcon");
                        menu.addListener();
                        delMenu();
                        addCTR();
                }
 
                public function addCTR():void
                {
                        ctr  = new ControllerForLevels(_stage);
                        addChild(ctr);
                        ctr.addlevel_1();
                        ctr.addEventListener("END_LEVEL", onEndLevel);
                }
 
                public function onEndLevel(event:Event):void
                {
                        delCTR();
 
                        addMenu();
                        this.addChild(menu);
                }
 
                public function delCTR():void
                {
                        removeChild(ctr);
                        ctr.removeEventListener("END_LEVEL", onEndLevel);
                }


Как быть?

Заранее спасибо!

Добавлено через 2 часа 36 минут
Может кто сталкивался, подскажите, что не так

illuzor 18.11.2013 23:51

Код AS3:

menu.addEventListener("CLICK_ICON", onClickIcon);

Код AS3:

this.removeEventListener("CLICK_ICON", onClickIcon);

Слушатель вы вешаете на menu, а удаляете с this. Хотя, не думаю, что проблема в этом.

in4core 19.11.2013 00:00

Проблема в коде, особенно в классе Model который принимает стейдж в конструкторе.

zCHESNOKz 19.11.2013 00:31

Цитата:

Сообщение от in4core (Сообщение 1152910)
Проблема в коде, особенно в классе Model который принимает стейдж в конструкторе.


По твоему этого не должно быть?

in4core 19.11.2013 00:58

По моему - почитайте, что такое модель прежде чем писать ересь. Код ужасен, нечитабелен и бредов. Неудивительно , что ничего нормально не работает.
Я удивляюсь современным игроделам, правда, чтоли все так на соплях держится?

Isfet 19.11.2013 10:44

события мыши (клик, даун, ап и т.д) срабатывают лишь на том объекте, на который вы повешали слушателя, если слушателя вешаете на кнопку, а потом ее удаляете, то куда бы вы дальше не кликнули событие не сработает, аналогично с меню, каким образом оно должно работать если вы удалили меню? создали новый экран, на него и вешайте новое событие клика, удалили экран, удалили подписку на событие, опять создали , опять подписались. и Вообще - да код ужасен, советую не использовать MVC, пока не поймете как работают все классы, которые вы используете.

Hauts 19.11.2013 11:28

Цитата:

По моему - почитайте, что такое модель прежде чем писать ересь. Код ужасен, нечитабелен и бредов. Неудивительно , что ничего нормально не работает.
Я удивляюсь современным игроделам, правда, чтоли все так на соплях держится?
Весьма смелое и грубое утверждение, учитывая, что человек учится и спрашивает, как сделать лучше. Да и судить про "современных игроделов" и про то, на чем "всё" дежрится — это смело. Я б себе такого не позволил.

И сдается мне, никто из нас не писал чего-либо по всем правилам и канонам с первого раза. В общем, нельзя так.

Psycho Tiger 19.11.2013 11:36

Цитата:

Сообщение от in4core
Проблема в коде, особенно в классе Model который принимает стейдж в конструкторе.

А ещё там проблёскивает наследование от дисплей обджекта, а, следовательно, узкое мышление о том, что модель – это модель данных – здесь не работает.
Уже представляю, как ты вечерами хвастаешься друзьям, что всю ночь провозился с моделью ...

@Автор, тащить в DisplayObject stage – дурная затея. У них stage уже есть, надо только дождаться, когда он станет доступен (событие ADDED_TO_STAGE).
Проблема же сидит в такой штуке, как в фокусе. Чтобы проще понять – представь страницу с 2 текстовыми полями. При нажатии клавиш печататься символы будут в то поле, в котором есть фокус. Соответственно, при сих манипуляциях фокус теряется и события перестают выстреливать.
Решение: вешать клавиши на stage. У неё всегда есть фокус.

zCHESNOKz 19.11.2013 13:19

Цитата:

Сообщение от Psycho Tiger (Сообщение 1152953)
А ещё там проблёскивает наследование от дисплей обджекта, а, следовательно, узкое мышление о том, что модель – это модель данных – здесь не работает.
Уже представляю, как ты вечерами хвастаешься друзьям, что всю ночь провозился с моделью ...

@Автор, тащить в DisplayObject stage – дурная затея. У них stage уже есть, надо только дождаться, когда он станет доступен (событие ADDED_TO_STAGE).
Проблема же сидит в такой штуке, как в фокусе. Чтобы проще понять – представь страницу с 2 текстовыми полями. При нажатии клавиш печататься символы будут в то поле, в котором есть фокус. Соответственно, при сих манипуляциях фокус теряется и события перестают выстреливать.
Решение: вешать клавиши на stage. У неё всегда есть фокус.



На счет фокуса ты прав, спасибо, в этом то и была проблема. Да, если вешать клавиши на stage, то все работает, но в игре будет, уйма различных кнопок, а на сколько я помню, как утверждал Volsh на стейдж лучше ничего не размещать. Вот я и думаю, а не лучше ли будет просто изменять фокус, - stage.focus = нужный элемент; или все таки это будет не правильно, или предоставлять какие то проблемы? Вообщем, что лучше?

Psycho Tiger 19.11.2013 13:36

Нет, подписываться на stage – вполне нормальная тема. У тебя есть ссылка на какой-то объект, так почему бы не послушать, что он там вещает?
Плохая затея что-то со stage делать – например, класть туда детей (addChild), или менять не знаю, прозрачность? ) Скорее всего об этом и говорил Wolsh.

По хорошему, вообщем-то, вынести всю клавиатурную логику в отдельное место, в отдельный класс, который будет вещать уже всем желающим о клавиатуре. Клавиатура у пользователя одна, так что вполне уместно сделать класс полностью из статичных полей – и ссылок тянуть не надо.
Почему это по хорошему? Ну, скажем, в будущем обнаружится, что если кнопку давить – то события начинают спамиться о том что кнопку быстро-быстро нажимают. Обычно этот эффект нежелателен, и в случае с отдельным классом вставить фикс придется только в этом одном месте.

Wolsh 19.11.2013 13:47

Артём, у стейджа нет прозрачности (IllegalOperationError)))))
Слушать стейдж совершенно нормально, он же плеер.
Ненормально отправлять детей в открытый космос в неизвестность на стейдж.

zCHESNOKz 19.11.2013 13:53

Цитата:

Сообщение от Psycho Tiger (Сообщение 1152964)
Нет, подписываться на stage – вполне нормальная тема. У тебя есть ссылка на какой-то объект, так почему бы не послушать, что он там вещает?
Плохая затея что-то со stage делать – например, класть туда детей (addChild), или менять не знаю, прозрачность? ) Скорее всего об этом и говорил Wolsh.

По хорошему, вообщем-то, вынести всю клавиатурную логику в отдельное место, в отдельный класс, который будет вещать уже всем желающим о клавиатуре. Клавиатура у пользователя одна, так что вполне уместно сделать класс полностью из статичных полей – и ссылок тянуть не надо.
Почему это по хорошему? Ну, скажем, в будущем обнаружится, что если кнопку давить – то события начинают спамиться о том что кнопку быстро-быстро нажимают. Обычно этот эффект нежелателен, и в случае с отдельным классом вставить фикс придется только в этом одном месте.

мой кейменеджер
Код AS3:

package
{
        import flash.display.Stage;
        import flash.events.KeyboardEvent;
 
        public class KeyboardManager
        {
                static private var keys:Array = [];
 
                static public function init(_stage:Stage):void
                {
                        _stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDownHandler);
                        _stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUpHandler);
                }
 
                protected static function onKeyUpHandler(event:KeyboardEvent):void
                {
                        keys[event.keyCode] = false;
                }
 
                protected static function onKeyDownHandler(event:KeyboardEvent):void
                {
                        keys[event.keyCode] = true;
                }
 
                static public function isKeyDown($keyCode:int):Boolean
                {
                        return keys[$keyCode];
                }
        }
}

Выходит класс меню будет выглядеть так ?
Код AS3:

package Menu
{
        public class GameMenu extends Sprite
        {
                public var icon:_iconLevel;
 
                public function GameMenu()
                {
                        this.addEventListener(Event.ADDED_TO_STAGE, onAddStage);
                }
 
                protected function onAddStage(event:Event):void
                {
                        this.removeEventListener(Event.ADDED_TO_STAGE, onAddStage);
 
                        icon = new _iconLevel();
                        stage.addChild(icon);
 
                        addListener();
                }
 
                public function addListener():void
                {
                        icon.addEventListener(MouseEvent.MOUSE_DOWN, onClick);
                }
 
                public function onClick(event:MouseEvent):void
                {
                        dispatchEvent( new Event("CLICK_ICON"));
                }
 
        }
}


Psycho Tiger 19.11.2013 18:38

Кейменеджер годится.
Только конвенция наименования... Во флеше принято использовать префикс "_" перед приватными переменными, а не параметрами. То есть в init просто stage, а keys как раз _keys. Знак доллара – указание, что метод проксирует зафинализированный. protected для статиков – ну, это... это нужно очень понимать, зачем :) Лучше private.

Про класс меню, как раз таки,
Код AS3:

stage.addChild(icon);

не надо так.

Надо icon положить в себя (в GameMenu). GameMenu же добавится в root тобой же. (это главный класс приложения, обычно его называют Main). А root уже сам флешплеер положит на stage. Получится,
stage -> root -> GameMenu -> icon. Всё логично, от большего-к-меньшему, и никто не ломится куда-то ввысь.
Т.к. stage здесь не нужен, то код можно сжать как-то так:
Код AS3:

package Menu
{
        public class GameMenu extends Sprite
        {
                public var icon:_iconLevel; //классы лучше называть с большой буквы, без подчеркивания вначале
 
                public function GameMenu(){
                        icon = new _iconLevel();
                        addChild(icon);
                        icon.addEventListener(MouseEvent.MOUSE_DOWN, onClick);
                }
 
                public function onClick(event:MouseEvent):void{
                        dispatchEvent( new Event("CLICK_ICON"));
                }
 
        }
}



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

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