|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Регистрация: Mar 2015
Сообщений: 64
|
Пользовательские события. Композиция.
Доброго времени суток.
Разрабатываю небольшую игру. Проблема возникла когда реализовывал смерть персонажа. Чтобы оповестить все классы о смерти персонажа решил использовать собственное событие. Поскольку класс персонажа уже расширяет класс Sprite, а реализовывать интерфейс IEventDipatcher не очень хочется (просто не знаю как) решил создать отдельный класс расширяющий EventDispatcher. Внутри этого класса есть открытый метод внутри которого создается новое событие. В классе персонажа создается экземпляр класса унаследованного от EventDispatcher и используя композицию вызывается метод создающий новое событие. Во всех остальных классах также создаются экземпляры класса унаследованного от EventDispatcher и подписываются на это событие. Проблема: событие не срабатывает (слушатели не вызываются), никаких ошибок и исключений нет. Привожу код (код я специально сильно упростил). Класс события: package { import flash.events.Event; import flash.events.EventDispatcher; public class GameOverEvent extends EventDispatcher{ public static const GAME_OVER:String = "gameOver"; public function GameOverEvent(){ } internal function gameOverListener():void{ dispatchEvent(new Event(GameOverEvent.GAME_OVER)); } } } package { import flash.utils.Timer; import flash.events.*; public class Compozition{ private var timer:Timer; private var gameOverEvent:GameOverEvent; public function Compozition(gameOverEvent){ gameOverEvent = new GameOverEvent(); timer = new Timer(1000); timer.addEventListener(TimerEvent.TIMER, endListener); timer.start(); } private function endListener(e:TimerEvent):void{ if(timer.currentCount == 10){ gameOverEvent.gameOverListener(); } } } } package { import flash.display.Sprite; import flash.utils.Timer; import flash.events.*; public class MySprite extends Sprite{ private var timer:Timer; private var gameOver:GameOverEvent; public function MySprite(){ this.x = 200; this.y = 300; timer = new Timer(1000); timer.addEventListener(TimerEvent.TIMER, moveListener); timer.start(); gameOver = new GameOverEvent(); gameOver.addEventListener(GameOverEvent.GAME_OVER, gameOverListener); } private function moveListener(e:TimerEvent):void{ this.x += 5; } private function gameOverListener(e:Event):void{ timer.stop(); timer.removeEventListener(TimerEvent.TIMER, moveListener); trace("сработало пользовательское событие"); } } } |
|
|||||
А ничего, что Sprite уже является EventDispatcher'ом? Нужно в документацию заглядывать хоть время от времени
Всю эту конструкцию можно смело удалять, и слать события прямо из персонажа. п.с. А не работает эта конструкция потому, что там каждый раз новый GameOverEvent создается. То есть для каждоо экземпляра он свой. Естественно они не смогут слушать события других экземпляров. Если нужно, чтобы эта конструкция работала, объект должен быть один и тот же. Допустим, сделанный синглтоном. |
|
|||||
Регистрация: Mar 2015
Сообщений: 64
|
Цитата:
И насчет нескольких экземпляров GameOverEvent. У Мука вычитал следующие (как раз он рассказывает как как сделать пользовательское событие "gameOver"): Цитата:
и всех их подписать на события создаваемые в классе Game (в моем случае GameOverEvent). Я не совсем понимаю что вы имели ввиду под "То есть для каждого экземпляра он свой", под "он" имеется ввиду создаваемое событие в методе gameOverListener()? |
|
|||||
Регистрация: Jul 2009
Сообщений: 149
|
1)Создавать дополнительный EventDispatcher нет необходимости. EventDispatcher входит в цепочку наследования Sprite(caseyryan вам даже скриншот выложил). Т.е., если ваш герой унаследован от Sprite, он сам может спокойно рассылать события
2)Почему не работает у вас. Вы рассылаете событие одним экземпляром GameOverEvent, а слушаете(ждете) это событие от другого экземпляра. У вас сейчас что то типа этого: var eventName:String = "someEvent"; var dispatcherA:EventDispatcher = new EventDispatcher(); var dispatcherB:EventDispatcher = new EventDispatcher(); dispatcherA.addEventListener(eventName, eventHandlerA); dispatcherB.addEventListener(eventName, eventHandlerB); dispatcherA.dispatchEvent(new Event(eventName)); private function eventHandlerA(e:Event):void { trace("dispatherA");//Этот трейс выполнится } private function eventHandlerB(e:Event):void { trace("dispatherB");//А этот не выполнится пока dispatcherB не "плюнет" событие } вы присваиваете переменной переданной в конструктор Compozition новый экземпляр GameOverEvent, т.е. вот тут, по идее, должна выскочить ошибка, т.к. gameOverEvent там будет null |
|
|||||
Регистрация: Mar 2015
Сообщений: 64
|
Спасибо разобрался.
|
|
|||||
Регистрация: Aug 2014
Адрес: Где-то на поверхности планеты, какой хз
Сообщений: 113
|
проще говоря достаточно просто создать новый класс Event, и там где ты хочешь чтобы вызывалось это событие пишешь
конкретнее эту строку нужно писать там где ты проверяешь будет ли вызваться событие или нет к примеру в таймере проверяешь здоровье бойца и как только здоровье упало до нуля или ниже. вещаешь строчку. Вот как я делаю
//СМЕРТЬ ПРИ здоровье = 0; if ((Characteristics.Health <= 0)&&(this.Died == false)) { //если проверять только здоровье во фрейме или таймере событие будет вызываться с каждым обновлением а так вызывается только 1 раз. Characteristics.Health = 0; Died = true; dispatchEvent(new PlayerAction(PlayerAction.DIE)); trace('игрок умер'); } |
Часовой пояс GMT +4, время: 12:03. |
|
« Предыдущая тема | Следующая тема » |
|
|