Hands to work!
To do this, you'll need download the source of NResponder:
For now we just will create a project that print (trace) some responses on the screen.
So you'll need an IDE to compile and debug the code, like Flash Professional, Flash Builder, Flash Develop, FDT, etc.
OK, now let's code!
Static or instantiated mode
The first important thing is import the NResponder to your classes. Some IDEs do this automatically for you (Flash Builder, FDT, Flash Develop,...) when you are typing.
NResponder package is inside the "appkit" (a SubFramework of Nineveh Framework) and inside the package "responders".
This path is just a convention of Nineveh Framework. Of course, you will need to import this package in all classes that you want to use NResponder.
public class Main
public function Main():void
Now, about the static and instantiated mode. Every time you add a new NResponder (register an event, add a call back function, register a listener, whatever, is the same thing for NResponder), the NResponder will create a little instance of Responder, this instance go to the core of NResponder and will be the responsible to execute the commands in the engine's core. This is a behavior, NResponder always will do this.
The cool thing here is that you can get a copy of this instance when you add a new. And you have some flexible ways to do this:
IMPORTANT: The following code is not real, is just to illustrate the both modes. In the next section (Creating a NResponder) you'll see a real code.
public class Main
public function Main():void
// This is the static mode
// This is the instantiated mode.
responder = new NResponder();
// Or even
responder = NResponder.add();
You could asking: "wait, why the 'new' create an instance and the static call return an instance too?"
Well, you'll understand soon, the "new" constructor is generic, and the static "adds" (in plural) have some shortcuts to you. As I mentioned early, the the NResponder can work with native events in Flash, so the different "adds" help you to create it. Although the "new" constructor can do this, you need to pass more parameters to it.
The static and instantiated mode don't have any impact in performance of memory of your application. The unique reason to use instantiated is if you need to change some behaviors of NResponder after create it. Like pause it without delete it, for example. But if you don't need later changes, don't worry with any instance.Creating a NResponder
Now let's see how to set a call back function to an event in Flash, or more directly, to create a NResponder. Here more than just define your listener, you'll specify the Action (same as Type in EventDispatcher's language) and all kind of things that NResponder will do for you.
IMPORTANT: Is here, in this section that you can say "Good bye" to EventDispatcher!
OK, the first thing that I want to show is like you normally do with EventDispatcher. When you want to use a custom event you do something like this:
myDispatcher.addEventListener('myCustomEventType', callBackFunction, false, 0, true);
This is terrible!
Because the only way to you dispatch your CustomEvent is using the "myDispatcher" instance! And look at this line of addEventListener, it is so big, unnecessary.
Now to do the same thing with NResponder all that you need is:
We'll talk about "dispatch" later, but for now, as you can see, you don't need to worry with additional parameters like use capture, use weak references, because NResponder don't need these kind of things to work with NResponder. Here is a little difference between the EventDispatcher and NResponder. The
is the type of event to EventDispatcher, but NResponder called it of "Action". So henceforth let's call "Action" everything that means "Event Type" for EventDispatcher.
And as I told above, you can get a reference to the instance returned by the "add" method:
var myReponder:NResponder = NResponder.add('myCustomEventType', callBackFunction);
Remember that this instance doesn't change anything, is just to you gain more control over the NResponder instance.
OK, now let's take a look at the NResponder working with native Event API of Flash. The method to create is very similar. If you want to set a click in a button, for example, using the native Event API you probably do something like this:
var myButton:CustomButton;// probably inherited from MovieClip or Sprite.
myButton.addEventListener(MouseEvent.CLICK, clickFunction, false, 0, true);
OK, now let's translate this to NResponder's language:
var myButton:CustomButton;// probably inherited from MovieClip or Sprite.
NResponder.addNative(myButton, MouseEvent.CLICK, clickFunction);
Just simple as it. Using the method "addNative" is very similar to "add", with only one difference: the first parameter is the target of the native Event.
Some people get confused at this point. But all that you need to remember is to ask "Who is responsible for dispatch this native event? Who is inherited from EventDispatcher class?", so you take this object and pass it on the first parameter to "addNative" method.
You can use NResponder to all kind of native events. The benefits is that it will work faster, more clean and you can use all the features of the NResponder. The following topics will explain about these features.
Well, as you noticed, as a Good Practice in programming to avoid misspelling, is advisable to you store your custom Actions in a class with "public static constants", like this:
public static const CUSTOM_ACTION:String = 'myCustomAction';
This is just a tip, although in this article to simplify the purposes I'll use literal strings to illustrate the examples.
Dispatch and arguments
After create a NResponder with the "adds" methods (add() and addNative()) you can dispatch these responders from anywhere in your application, even in different SWF files (loaded files in the same application).
All that you need is inform the "Action" you want to dispatch and the parameters that you want, if needed.
// This will dispatch "myAction" with no arguments. So the callBack function don't need to expect any parameter.
// This will dispatch "anotherAction" with the arguments 35 (Number) and "aString" (String)
// So the callBack function should expect these parameter (Number and String in this order).
NResponder.dispatch('anotherAction', [35.5, 'aString']);
The dispatch() method is simple, it will dispatch the specified Action to the whole application.
OK, so you could ask "If NResponder will dispatch an Action for anyone that was registered in NResponder, what it'll do with buttons, for example? Will dispatch a click to all? How it'll know for what button to dispatch?".
The answer is: using the Target parameter!
Do you remember in addNative() that you need to specify the Target as the first parameter? Is now that it makes the difference.
If you specify a target when create a NResponder, that target will work like a lock and this NResponder will only respond when it's target is specified.
Well, this can seems a little confused now, but just think that NResponderCore will care about this for you. If you are using a native event, like MouseEvents, KeyboardEvents or any other, this will happens automatically during the dispatch. Just don't care about it.
If you want, you can specify a target without use the native events. You may use this to take the benefits of this "lock" that target provides. But this is a more advanced topic and I don't want to confuse you with this here. If you want to know more about this just check this Wiki of the project:http://code.google.com/p/nineveh-responder/wiki/DispatchAdvanced
Let's move.Number of replies
As I told you, this is one of the most interesting features to me. This let you specify how many times you want that a NResponder performs and after the last one, it will automatically be removed and cleaned. All that you need is specify a number after the listener parameter in the "adds" methods.
NResponder.add('myCustomEventType', callBackFunction, 5);
NResponder.addNative(myButton, MouseEvent.CLICK, clickButton, 2);
NResponder.addNative(this, Event.ADDED_TO_STAGE, init, 1);
[/as]The code above means that:
You can specify how many times you want. Obviously just can't specify negative number of times.
myCustomEventType" will only response 5 times
- The CLICK on "myButton" will happens just 2 times
- The "init" listener will happens just once when the target "this" be placed on the stage.
And just for convention, the 0 (default) number means that NResponder will be performed infinitely.
The delay time is the minimum time necessary between two consecutive dispatches.
Imagine that you have a button in your game and don't want that the user click on it without stop. You want the at least the user waits 2.5 sec until make a new click. Well, all that you need is specify the next parameter after the number of replies in the "adds" methods.
NResponder.addNative(myButton, MouseEvent.CLICK, clickButton, 0, 2.5);
This means that the "clickButton" listener just will happens again if the next click occur after 2.5 sec. If the user make a click during the delay of 2.5 sec that click will be ignored.
The 0 (default) means "no delay".Has and remove
Just like the EventDispatcher class, NResponder provide a way to you check what is registered inside the NResponderCore and a way to remove it.
The advantage here is that you can combine and do multiple tasks at once.
Let's start with a simple case, you want to know if has in your application any registered Action of "myAction", so:
This will return "true" if you have at least one registered NResponder with "myAction". Now, imagine that you want to know if have "myAction" linked with a specific callBack function.
This will return "true" if you have at least one registered NResponder with "myAction" as Action and "myFunction" as Listener.
And at last, you can check if this is true for a specific target.
NResponder.has('myAction', myFunction, myTarget);
This will return "true" if you have at least one registered NResponder with "myAction" as Action and "myFunction" as Listener and "myTarget" as Target.
The fun thing here, is that you can combine these 3 parameters. At this way:
NResponder.has('myAction', null, myTarget);
NResponder.has(null, myFunction, myTarget);
NResponder.has(null, myFunction, null);
NResponder.has(null, null, myTarget);
The four line above means:
- Has at least one registered NResponder with "myAction" as Action and "myTarget" as Target?
- Has at least one registered NResponder with "myTarget" responding to "myFunction"?
- Has at least one registered NResponder responding to "myFunction", independently of Actions and Target?
- Has at least one registered NResponder with "myTarget" as target, independently of callBack functions and Actions?
means that you want to ignore that parameter and focus on the others. These combination can be very helpful in the case that you don't have more access to one or two of those parameters.
But the most helpful of the combination feature is on remove. You can remove a lot of NResponders with just one line of code.
The remove() method works exactly same as has() method:
NResponder.remove(null, null, myTarget);
The line above means that you'll remove all the NResponder of a specific Target ("myTarget").
Now think of a button. You can register a NResponder to the "Mouse Over" action, another one to the "Mouse Out", another to "Mouse Down", one to "Mouse Up" and one "Mouse Move". Well, 5 NResponders. And after, when you don't want this button anymore, you can remove all these NResponder in just one line, like this:
NResponder.addNative(myButton, MouseEvent.MOUSE_OVER, overFunction);
NResponder.addNative(myButton, MouseEvent.MOUSE_OUT, outFunction);
NResponder.addNative(myButton, MouseEvent.MOUSE_DOWN, startDragFunction);
NResponder.addNative(myButton, MouseEvent.MOUSE_UP, stopDragFunction);
NResponder.addNative(myButton, MouseEvent.MOUSE_MOVE, draggingFunction);
NResponder.remove(null, null, myButton);
Remember that NResponderCore is responsible for all clean, and it will know exactly how to clean everything with just one line of remove() method.Benefits of instantiated mode
With instantiated mode you can change the order of dispatches of the same Actions, you can perform the call back function directly, you can check some attributes of that instance of NResponder, change the values of delay, number of replies, etc.
I'll not talk about all this kind of benefits, you can find information about they at the Wiki of Project page and at docs:http://code.google.com/p/nineveh-responder/w/listhttp://db-in.com/frameworks/nineveh/doc/
But I want to talk here about a benefit called "paused". This property is a boolean where "true" indicate paused.
As the name suggest, you can pause the NResponder without remove it. This can be very helpful if you want to interrupt a NResponder just for a while.
For example, imagine that in your application you have a 3D interface that react to mouse position. But if the user hit the space bar will appear a pop-up and for the time the user stay on this pop-up you want your 3D interface stop to react to mouse position.
Well, all that you need is use NResponder in instantiated mode and pause it when you need.
var myResponder:NResponder = NResponder.addNative(my3DInterface, MouseEvent.MOUSE_MOVE, interactFunction);
// When start the pop-up, use this to pause this NResponder.
myResponder.paused = true;
// When close the pop-up, use this to reactivate this NResponder again.
myResponder.paused = false;
Obviously you can remove and add the NResponder again using the static mode, but at this way you save CPU and memory, because pause is much much faster than add and remove.
Here I presented to you some features, the most important and most used, of the NResponder Engine. Remember to check the project page to see everything about NResponder. For now, this is all that we need to "say Good Bye to EventDispatcher". With just these features you can do almost everything with NResponder.
Now let's move to some real world example!