REAL WORLD example

Finally let's see a real example of NResponder working. Now you'll need the project files, you can download it in the link below:



At a glance
In this example we will create a very simple shoot game's routine. To show you how the features and benefits of NResponder can change how you think about your work, let's refine a little this shoot game. Imagine that the gun in this game is an old single-action revolver, so at every shoot the hammer of this revolver needs to be pulled again and this action may take about 1.5 sec. And more, the gun just has 6 bullets, after 6 shots the user must reload the gun.

First let's imagine what we need to construct this with the native Event API, how many Booleans, timers, a lot of "if then else", and variables we need to use to achieve this behavior. I'll show a possible way to do this, but in the middle, before the code start to be more complex, with a lot of annoying things, we'll change and use the NResponder.

Now, about the project files, is important to say that I place some two-handed comments. You know, that kind of
comment block that you can toggle on/off between two codes. Like this:

/*
...
/*/

The code here is activated.
//*/

---------

//*
The code here is activated.
/*/
...
//*/


So in the project files I let this kind of comment to you see the difference between the native Event API and NResponder. You can easily toggle between both adding a "/" at the first line of the comment block.

Oh right, let's start!

Constructing with native Event API
At this point I'm sure you already look at the project files. So I'll just describe what you've found in FLA file:



Nothing new here, just a stage with 3 MovieClips: the shot area, the reload button and the bullets.
Inside the bullets MovieClip we have a MovieClip for each bullet. All these has instance names that we'll use in the main class later.
As you can see, in the library we export a view called VShootAnimation. Just is just a view class to control the animation of the shoot using a texture atlas (poof.png).

Now I'll start with the NResponderExample just using the native Event API.

/**
 * NResponderExample class
 *
 * @version NResponderExample v1.0
 * @author Diney Bomfim
 */

package
{
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
   
    /**
     * Simple shoot game to illustrate the usage of NResponder.
     */

    public dynamic class NResponderExample extends MovieClip
    {
       
    //**************************************************
    //  Protected / Private Properties
    //**************************************************
       
        private var shoots:int;
       
    //**************************************************
    //  Initialization
    //**************************************************
       
        /**
         * The initialization of NResponderExample class.
         */

        public function NResponderExample():void
        {
            if (stage)
            {
                init(null);
            }
            else
            {
                addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
            }
        }
       
    //**********************************************************************************************************
    //
    //  Protected / Private Methods
    //
    //**********************************************************************************************************
       
        /**
         * Initiate the View of the application.
         *
         * @param    e
         */

        private function init(e:Event):void
        {
            // Remove the listener
            removeEventListener(Event.ADDED_TO_STAGE, init);
           
            // Definitions
            doReload(null);
           
            // Listeners
            this.btReload.addEventListener(MouseEvent.MOUSE_DOWN, doReload, false, 0, true);
        }
       
        /**
         * Make a Shoot on the valid stage area.
         *
         * @param    e
         */

        private function doShoot(e:MouseEvent):void
        {
            trace('a Shoot');
           
            var shootAnim:VShootAnimation = new VShootAnimation();
            shootAnim.x = stage.mouseX;
            shootAnim.y = stage.mouseY;
           
            addChild(shootAnim);
           
            this.mcBullets['mcBullet' + shoots].visible = false;
           
            ++shoots;
        }
       
        /**
         * Reload the gun.
         *
         * @param    e
         */

        private function doReload(e:MouseEvent):void
        {
            shoots = 1;
           
            for (var i:int = 1; i <= 6; i++)
            {
                this.mcBullets['mcBullet' + i].visible = true;
            }
           
            // Listeners
            this.mcShootArea.addEventListener(MouseEvent.MOUSE_DOWN, doShoot, false, 0, true);
        }
    }
}


Well, the above class will be our main class of the FLA file.
  • First in the constructor of the class (NResponderExample()), just to follow a best practice we put Event.ADDED_TO_STAGE to guarantee that no errors will happens if this file is loaded by another SWF file.
  • In the init() method we remove the previously Event.ADDED_TO_STAGE, make the first reload to the gun and add the listener of the reload button.
  • In the doReload() method we make all the bullets inside the mcBullets visible again and add the listener that will make the shoots.
  • In the doShoot() method we place our VShootAnimation view class in the mouse screen position and remove one bullet from the screen.
At this point the code remains simple.
But our minimally refined behavior is not implemented yet. The bullets don't has a delay to simulate the old revolver, the shoots don't stop after the sixth and we have a bug in the line this.mcBullets['mcBullet' + shoots].visible = false; when the shoots don't stop after the sixth.

Well, try to think what should be necessary to implement our behavior.
Take some minutes if necessary looking at this code and try to implement this behavior.
Remember all the problems above.

To do this we would probably place a lot of "if then else" in our code, create timer checks, Booleans, oh god... really boring!

But let's STOP here and migrate all our events to NResponder Engine.


Solving the problems with NResponder
Now is the BIG POINT of this article. Is now! Is here!
Is here that the magic happens with NResponder!
Believe or not, but to solve ALL these problems, to implement our behavior to the above code, ALL that we need is to REPLACE 3 LINES of code and even can EXCLUDE ONE!!!

Just it, nothing more!

/**
 * NResponderExample class
 *
 * @version NResponderExample v1.0
 * @author Diney Bomfim
 */

package
{
    import flash.display.MovieClip;
    import flash.events.Event;
    import flash.events.MouseEvent;
   
    import appkit.responders.NResponder;
   
    /**
     * Simple shoot game to illustrate the usage of NResponder.
     */

    public dynamic class NResponderExample extends MovieClip
    {
       
    //**************************************************
    //  Protected / Private Properties
    //**************************************************
       
        private var shoots:int;
       
    //**************************************************
    //  Initialization
    //**************************************************
       
        /**
         * The initialization of NResponderExample class.
         */

        public function NResponderExample():void
        {
            if (stage)
            {
                init(null);
            }
            else
            {
                /*
                addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
                /*/

                NResponder.addNative(this, Event.ADDED_TO_STAGE, init, 1);
                //*/
            }
        }
       
    //**********************************************************************************************************
    //
    //  Protected / Private Methods
    //
    //**********************************************************************************************************
       
        /**
         * Initiate the View of the application.
         *
         * @param    e
         */

        private function init(e:Event):void
        {
            // Remove the listener
            //removeEventListener(Event.ADDED_TO_STAGE, init); // Don't need this any more.
           
            // Definitions
            doReload(null);
           
            // Listeners
            /*
            this.btReload.addEventListener(MouseEvent.MOUSE_DOWN, doReload, false, 0, true);
            /*/

            NResponder.addNative(this.btReload, MouseEvent.MOUSE_DOWN, doReload);
            //*/
        }
       
        /**
         * Make a Shoot on the valid stage area.
         *
         * @param    e
         */

        private function doShoot(e:MouseEvent):void
        {
            trace('a Shoot');
           
            var shootAnim:VShootAnimation = new VShootAnimation();
            shootAnim.x = stage.mouseX;
            shootAnim.y = stage.mouseY;
           
            addChild(shootAnim);
           
            this.mcBullets['mcBullet' + shoots].visible = false;
           
            ++shoots;
        }
       
        /**
         * Reload the gun.
         *
         * @param    e
         */

        private function doReload(e:MouseEvent):void
        {
            shoots = 1;
           
            for (var i:int = 1; i <= 6; i++)
            {
                this.mcBullets['mcBullet' + i].visible = true;
            }
           
            // Listeners
            /*
            this.mcShootArea.addEventListener(MouseEvent.MOUSE_DOWN, doShoot, false, 0, true);
            /*/

            NResponder.addNative(this.mcShootArea, MouseEvent.MOUSE_DOWN, doShoot, 6, 1.5);
            //*/
        }
    }
}


As you can see, first using the feature of "number of replies" we make our Event.ADDED_TO_STAGE listener run once and automatically be excluded.
With the same feature we make our gun dispatch just 6 times and stop.
And using the delay behavior we make our gun wait 1.5 sec between two consecutive shoots.

Well, literally, you can say "Good Bye" to EventDispatcher in your application!


Conclusion
Well, obviously that I show an specific example where the NResponder fits perfect and you can think that this is just a isolated example.
Well, just remember all the features and facilities that I told you here, remember to check the project page and the docs to know all the power of NResponder.
But if you still have doubts about how helpful and powerful NResponder can be, I just want that you remember two things, just two little things:
  • NResponder is completely independent, can dispatch from everywhere to everywhere and can carry everything with it.
  • With NResponder we can realize new things, new horizons that we don't realize before. Perhaps, before it, we just followed another ways.
Finally, hope I've helped you, hope you try NResponder, test it, try to replace in your own code, make some performance tests, in another words, ENJOY!

Again I'll place here the links about NResponder and if you have any doubt about NResponder, just email me!

Project page: http://code.google.com/p/nineveh-responder/
Blog page: http://db-in.com/blog/nineveh-framework/nresponder/
Download the NResponder: http://nineveh-responder.googlecode.com/files/Nineveh-Responder.zip

Thanks for everyone that read this article.

See you later!