Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 19.11.2015, 13:01
бакуард вне форума Посмотреть профиль Отправить личное сообщение для бакуард Найти все сообщения от бакуард
  № 1  
Ответить с цитированием
бакуард

Регистрация: Mar 2015
Сообщений: 64
По умолчанию Пользовательские события. Композиция.

Доброго времени суток.

Разрабатываю небольшую игру. Проблема возникла когда реализовывал смерть персонажа. Чтобы оповестить
все классы о смерти персонажа решил использовать собственное событие. Поскольку класс персонажа уже расширяет класс Sprite, а реализовывать интерфейс IEventDipatcher не очень хочется (просто не знаю как) решил создать отдельный класс расширяющий EventDispatcher. Внутри этого класса есть открытый метод внутри которого создается новое событие.
В классе персонажа создается экземпляр класса унаследованного от EventDispatcher и используя композицию вызывается метод создающий новое событие. Во всех остальных классах также создаются экземпляры класса унаследованного от EventDispatcher и подписываются на это событие.
Проблема: событие не срабатывает (слушатели не вызываются), никаких ошибок и исключений нет.

Привожу код (код я специально сильно упростил).

Класс события:
Код AS3:
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));
		}
 
	}
}
Код класса создающего экземпляр GameOverEvent и вызывающий метод gameOverListener использую композицию:
Код AS3:
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();
			}
		}
 
	}
}
Код класса подписывающегося на событие GameOverEvent.GAME_OVER:
Код AS3:
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("сработало пользовательское событие");
		}
 
	}
}
Подскажите пожалуйста, где может быть ошибка или возможно я вообще ерунду делаю.

Старый 19.11.2015, 13:06
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 2  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
А ничего, что Sprite уже является EventDispatcher'ом? Нужно в документацию заглядывать хоть время от времени
Всю эту конструкцию можно смело удалять, и слать события прямо из персонажа.

п.с. А не работает эта конструкция потому, что там каждый раз новый GameOverEvent создается. То есть для каждоо экземпляра он свой. Естественно они не смогут слушать события других экземпляров. Если нужно, чтобы эта конструкция работала, объект должен быть один и тот же. Допустим, сделанный синглтоном.
Миниатюры
Нажмите на изображение для увеличения
Название: Screenshot_1.jpg
Просмотров: 167
Размер:	43.1 Кб
ID:	31871  

Старый 19.11.2015, 13:44
бакуард вне форума Посмотреть профиль Отправить личное сообщение для бакуард Найти все сообщения от бакуард
  № 3  
Ответить с цитированием
бакуард

Регистрация: Mar 2015
Сообщений: 64
Цитата:
А не работает эта конструкция потому, что там каждый раз новый GameOverEvent создается. То есть для каждого экземпляра он свой. Естественно они не смогут слушать события других экземпляров. Если нужно, чтобы эта конструкция работала, объект должен быть один и тот же. Допустим, сделанный синглтоном.
То есть создаем один экземпляр GameOverEvent и просто передаем его в качестве аргумента конструктора того класса, где мы хотим вызывать его методы или подписаться на рассылаемые им события, а там внутри класса "получателя" сохраняем на него ссылку?

И насчет нескольких экземпляров GameOverEvent. У Мука вычитал следующие (как раз он рассказывает как как сделать пользовательское событие "gameOver"):

Цитата:
Любой экземпляр класса Game, создаваемый
классом Console, является получателем пользовательского события "gameOver",
которое возникает после окончания игры.
То есть я так понял можно создать множество экземпляров класса Game (в моем случае GameOverEvent)
и всех их подписать на события создаваемые в классе Game (в моем случае GameOverEvent). Я не совсем понимаю что вы имели ввиду под "То есть для каждого экземпляра он свой", под "он" имеется ввиду создаваемое событие в методе gameOverListener()?

Старый 19.11.2015, 15:47
ObOs вне форума Посмотреть профиль Отправить личное сообщение для ObOs Найти все сообщения от ObOs
  № 4  
Ответить с цитированием
ObOs
 
Аватар для ObOs

Регистрация: Jul 2009
Сообщений: 149
1)Создавать дополнительный EventDispatcher нет необходимости. EventDispatcher входит в цепочку наследования Sprite(caseyryan вам даже скриншот выложил). Т.е., если ваш герой унаследован от Sprite, он сам может спокойно рассылать события
Код AS3:
hero.dispathEvent(new Event("gameOver"));
2)Почему не работает у вас. Вы рассылаете событие одним экземпляром GameOverEvent, а слушаете(ждете) это событие от другого экземпляра. У вас сейчас что то типа этого:
Код AS3:
		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 не "плюнет" событие
		}
3)И во тут
Код AS3:
		public function Compozition(gameOverEvent){
			gameOverEvent = new GameOverEvent();
вы присваиваете переменной переданной в конструктор Compozition новый экземпляр GameOverEvent, т.е. вот тут, по идее, должна выскочить ошибка, т.к. gameOverEvent там будет null
Код AS3:
		private function endListener(e:TimerEvent):void{
			if(timer.currentCount == 10){
				gameOverEvent.gameOverListener();
				//Вот тут ошибка т.к. gameOverEvent==null
			}
		}

Старый 19.11.2015, 16:15
бакуард вне форума Посмотреть профиль Отправить личное сообщение для бакуард Найти все сообщения от бакуард
  № 5  
Ответить с цитированием
бакуард

Регистрация: Mar 2015
Сообщений: 64
Спасибо разобрался.

Старый 21.11.2015, 09:23
PsychoTech вне форума Посмотреть профиль Отправить личное сообщение для PsychoTech Найти все сообщения от PsychoTech
  № 6  
Ответить с цитированием
PsychoTech
 
Аватар для PsychoTech

Регистрация: Aug 2014
Адрес: Где-то на поверхности планеты, какой хз
Сообщений: 113
Цитата:
Сообщение от бакуард Посмотреть сообщение
Спасибо разобрался.
проще говоря достаточно просто создать новый класс Event, и там где ты хочешь чтобы вызывалось это событие пишешь
Код AS3:
this.dispatchEvent(new PlayerAction(PlayerAction.DIE));
конкретнее эту строку нужно писать там где ты проверяешь будет ли вызваться событие или нет к примеру в таймере проверяешь здоровье бойца и как только здоровье упало до нуля или ниже. вещаешь строчку. Вот как я делаю

Код AS3:
//СМЕРТЬ ПРИ здоровье = 0;
			if ((Characteristics.Health <= 0)&&(this.Died == false)) { //если проверять только здоровье во фрейме или таймере событие будет вызываться с каждым обновлением  а так вызывается только 1 раз.
				Characteristics.Health = 0;
				Died = true;
				dispatchEvent(new PlayerAction(PlayerAction.DIE));
				trace('игрок умер');
			}

Создать новую тему Ответ Часовой пояс GMT +4, время: 12:03.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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