Custom Events

Subscribe to Custom Events 17 posts

avatar for lan14n lan14n 47 posts
Flag Post

I am thinking of implementing a “help popup” using custom events. I haven’t used it before and I was wondering what people think about it.

I was thinking of having a custom event trigger once the player reaches a certain area. The function called by the listener will show a help pop up screen and would then remove the listener afterward.

e.g. The player enters a room with a treasure chest. An event dispatch will occur, and will call a function that will show a help file of a treasure chest. The function will then remove the listener.

My question is, how is the performance of a custom event compare versus a single “if” statement. The “if” statement stays forever and gets checked every time the certain event happens, while the listener gets deleted after the event is triggered. The bad side is I will have a lot of listeners.

Also, Is this a good idea to implement custom events for a help pop up screen.

If I misunderstood what custom events does, I would be happy if someone explained it to me. I haven’t really played around with it. Thanks.

 
avatar for NineFiveThree NineFiveThree 1370 posts
Flag Post

You could use one single listener, if you used bubbling to your advantage.

 
avatar for BobJanova BobJanova 857 posts
Flag Post

I haven’t used events within the gameplay before, but I don’t see any reason why it is a bad idea.

 
avatar for ErlendHL ErlendHL 1313 posts
Flag Post

I was entering the forums to ask if you can have custom events with addEventListener. Like
thing.addEventListener("needsToBeRedrawn", func);

But I’m not sure if it’s the same as this question.

 
avatar for BobJanova BobJanova 857 posts
Flag Post

Erlend, it’s not the same question, but related I think. You can (and it’s very useful!), but in order to be able to dispatch custom events, your class needs to extend from EventDispatcher. Then you use dispatchEvent(…) to fire an event.

 
avatar for Ace_Blue Ace_Blue 1087 posts
Flag Post

Here’s an example of a custom event class.

package  
{
	import flash.events.Event;
	public class GameEvent extends Event 
	{
		public static const TITLETONEWGAME:String = "Title to new game.";
		public static const TITLETOCONTINUE:String = "Title to continue.";
		public static const TITLETOUPGRADES:String = "Title to upgrades.";
		public static const TITLETOOPTIONS:String = "Title to options.";
		public static const GAMETOTITLE:String = "Game to title.";
		public static const GAMEREADY:String = "Game initialized and ready to start.";
		public static const UPGRADESTOTITLE:String = "Upgrades to title.";
		public static const OPTIONSTOTITLE:String = "Options to title.";
		public static const ENDINGTOTITLE:String = "Ending to title.";
		
		public function GameEvent(type:String)
		{
			super(type);
		}
	}
}

All you have to do is have your event dispatcher do dispatchEvent(new GameEvent(GameEvent.TITLETONEWGAME)); for instance, to dispatch a custom TITLETONEWGAME event. Basically it works exactly the same way as with standard events.

As for the help popup, I strongly recommend using an event: this way you can almost completely decouple the trigger (entering a room) and the effect (showing the tutorial).

What would be interesting to do, but I don’t know if it’s possible, is gather all tutorial trigger events (assuming you have more than one) in one custom event class and catch them all with the same listener, but I don’t know if that’s possible. As far as I know, a listener listens for one particular event, say TutorialAboutTreasure, but it would be very interesting to set it up to listen to the entire class of events. Like, say, all custom tutorial events, with the target function identifying the actual event and figuring out what to from there.

 
avatar for lan14n lan14n 47 posts
Flag Post

@ace_blue

thanks. I will try that out. That really helps.

 
avatar for Eu_Plon_Ka Eu_Plon_Ka 258 posts
Flag Post
Originally posted by Ace_Blue:

What would be interesting to do, but I don’t know if it’s possible, is gather all tutorial trigger events (assuming you have more than one) in one custom event class and catch them all with the same listener, but I don’t know if that’s possible. As far as I know, a listener listens for one particular event, say TutorialAboutTreasure, but it would be very interesting to set it up to listen to the entire class of events. Like, say, all custom tutorial events, with the target function identifying the actual event and figuring out what to from there.

You bring up an interesting idea, which I guess would require a custom event dispatching system. What I have laid out is part of that where you can overload the a listen method which will add event listeners for every superclass that has a specific listener. You can obviously get more creative than this, but may be a start.

class MyEventObject extends EventDispatcher {
	public EVENT:String = "myEvent";

	public listen(Function, Boolean, Int, Boolean) {
		this.addEventListner(EVENT, Function, Boolean, Int, Boolean);
	}
}

class OtherEventObject extends MyEvent {
	public OTHER_EVENT:String = "otherEvent";
	
	public listen(Function, Boolean, Int, Boolean) {
		super.listen(Function, Boolean, Int, Boolean);
		this.addEventListener(OTHER_EVENT, Function, Boolean, Int, Boolean);
	}
}

If you were to dispatch and event with name “myEvent”, then all the other events should be triggered as well. It should probably have more thought, since there is a possibility that the event could be fired more than once for a subclass.

 
avatar for Ace_Blue Ace_Blue 1087 posts
Flag Post
Originally posted by lan14n:

@ace_blue

thanks. I will try that out. That really helps.

You’re welcome. To give back to Caesar though, I learned to do it from this awesome tutorial series which I am happy to link to whenever possible.

 
avatar for BobTheCoolGuy BobTheCoolGuy 3755 posts
Flag Post

You could just have it dispatch TUTORIAL_EVENT events. Then, make the event hava a member called data or something, and that can hold an additional String. That way, you only need one EventListener. Also, make the events bubbling! That way, no matter where you dispatch them from, something lower can catch them.

 
avatar for Ace_Blue Ace_Blue 1087 posts
Flag Post

That’s genius Bob! A custom event could contain additional info as part of its definition. And I really need to read up on bubbling, I have no idea what it is.

 
avatar for BobTheCoolGuy BobTheCoolGuy 3755 posts
Flag Post
Originally posted by Ace_Blue:

That’s genius Bob! A custom event could contain additional info as part of its definition. And I really need to read up on bubbling, I have no idea what it is.

A quick example for you: I have this Sprite – we’ll call it SurveyScreen. Now for layout, SurveyScreen has all kinds of things on it. And these sprites, have other sprites, and, many layers up, there’s finally a bunch of TextFields and RadioButtons, on the sprites on other sprites, on SurveyScreen. Now in SurveyScreen’s class, I add eventlisteners listening for Event.CHANGE to each of the TextFields and RadioButtons. Since the event bubbles – it goes through all the layers of Sprites down to SurveyScreen, where I can process it. It’s quite convenient. If that didn’t make sense (which it may very well not of):

http://www.adobe.com/devnet/actionscript/articles/event_handling_as3.edu.html
http://help.adobe.com/en_US/as3/mobile/WS948100b6829bd5a67edfb831266c0b5fc6-8000.html
http://www.rubenswieringa.com/blog/eventbubbles-eventcancelable-and-eventcurrenttarget

 
avatar for Ace_Blue Ace_Blue 1087 posts
Flag Post

It does. You mean that instead of each level catching the event and dispatching an event to the level immediately above themselves, the listener on the very top can hear an event that got dispatched all the way at the bottom.* Powerful, but possibly dangerous. After all the SurveyScreen doesn’t need to know that some button in the depths of its hierarchy got clicked. It’s only preoccupied with the biggest-picture implications of it. I fear that bubbling could lead to flat design, where everything gets handled at the SurveyScreen level, just because it’s easier to have access to everything, even if that means bloating that class with low-level stuff that really shouldn’t be there.

*: I think we may have reversed concepts of ‘up’ and ‘down’ in this case. I tend to consider ‘topmost’ the element which contains everything else. I sense you might consider it the lowest, with all others ‘on’ it. I have no clue what the official nomenclature is.

 
avatar for NineFiveThree NineFiveThree 1370 posts
Flag Post
Originally posted by Ace_Blue:

Here’s an example of a custom event class.

package  
{
	import flash.events.Event;
	public class GameEvent extends Event 
	{
		public static const TITLETONEWGAME:String = "Title to new game.";
		public static const TITLETOCONTINUE:String = "Title to continue.";
		public static const TITLETOUPGRADES:String = "Title to upgrades.";
		public static const TITLETOOPTIONS:String = "Title to options.";
		public static const GAMETOTITLE:String = "Game to title.";
		public static const GAMEREADY:String = "Game initialized and ready to start.";
		public static const UPGRADESTOTITLE:String = "Upgrades to title.";
		public static const OPTIONSTOTITLE:String = "Options to title.";
		public static const ENDINGTOTITLE:String = "Ending to title.";
		
		public function GameEvent(type:String)
		{
			super(type);
		}
	}
}

this way you can almost completely decouple the trigger (entering a room) and the effect (showing the tutorial).

I don’t think this Event class is well decoupled if the purpose of it is hard coded into it in form of constants.

Rather have Events tied to what is happening, not what is supposed to happen after they occured.
A window/menu/whatever would dispatch an MenuEvent.CLOSE event,not a GameEvent.IM_THE_UPGRADES_MENU_OF_A_TETRIS_GAME_AND_I_GOT_CLOSED_SO_START_THE_TETRIS_GAME_AND_NO_OTHER_GAME_NOW ;)

Depending on the target of the close event, you decide what to do next. A state machine if you want to call it like that.

 
avatar for Ace_Blue Ace_Blue 1087 posts
Flag Post

OK, I’ll bite. So I got a title screen, on which are 4 buttons, labeled: ‘New Game’, ‘Continue’, ‘Upgrades’ and ‘Options’. The title screen doesn’t know what they do, just that they exist, and that it should dispatch a specific event when they make noise (they dispatch an onClick event when clicked and the title screen object has a listener on each of them.)

So one of them, let’s say ‘New Game’ gets clicked. It dispatches an onClick event, which title screen (and only title screen, nobody else even knows about these buttons) hears. So now title screen has to report that the new game button got clicked. How would you have me name that event? New_Game_Clicked? Anybody who ever cared about that already knows about it. What is happening right now is that the title screen is still being displayed, while it shouldn’t be, and the game screen, set up with a new game, is not showing, while it should be. What would you have me name that? We_Are_In_Deep_Doo_Doo is not quite specific enough, I’m afraid, and a tad too alarmist.

I could name it CLOSE, but then I would use the same event for all 4 buttons. How is the object above the title screen supposed to know what to do specifically with a CLOSE event from currentTarget title screen? Close title screen, sure, but then what? If clicking on any of the buttons causes title screen to dispatch the same event then the specificity of which button was clicked and therefore which action must be taken disappears.

I could completely bypass the title screen. When the ‘New Game’ button gets clicked, the Coordinator which handles the various screens could catch the event, identify the currentTarget as the New Game button that resides on the title screen and act accordingly. I could, except the coordinator has no business looking at buttons two levels below itself. That’s not its job. It’s interference of a high level object on the activities of a low level object, which creates expectations and dependencies that make modifying the code more difficult than it has to be, so a big no-no.

So I’m at a loss. I’m doing it wrong, OK, but how do I do it right?

 
avatar for BobJanova BobJanova 857 posts
Flag Post

Put an event handler on the title screen, for BUTTON_CLICK or something similar, and check e.target to find out which button was clicked. That’s the beauty of bubbling events, and although it can be abused I think it’s reasonable here: you can choose the most appropriate level to attach handlers. In this case having the menu dispatch button-click events seems fine.

 
avatar for Ace_Blue Ace_Blue 1087 posts
Flag Post

OK, so instead of having a listener for each button listening for the button’s onClick event I would have just one at the title screen level. That’s not the part that was irking 953, though. He was objecting to the naming convention of the next round of events, those that get dispatched by the title screen to alert the coordinator above that screens should be swapped.

My argument is that if I have a single event for that the coordinator won’t know which screen to remove (although it could infer it’s event.currentTarget, but that’s a tad risky) nor which screen to display. But if I have separate events then they must have distinct names, so what’s wrong with their names?