Blog

  • Animation Event Engine

    Not much of an engine, but I need to generate events when an animation completes, so devised this function to do so. It’s based on the start and stop frames of the animations being static variables; basically enumerated values.

    You pass in what function you want to run, where it’s at (scope), what timeline your looking in for the frame position, and what the target frame number is. So, if your character attacks on frame 10, and the animation completes on frame 20, and you want to call a function when it’s done, you’d do:

    static var ATTACK:Number = 10;
    this.gotoAndPlay(ATTACK);
    doWhenFrameReached("onDoneAttacking", this, this, 20);
    

    Main engine function below:

    function doWhenFrameReached(handler:String,
                                scope:Object,
                                timeline:MovieClip,
                                frameNumber:Number):Void
    {
            if(!process_mc){
                    createEmptyMovieClip("process_mc", getNextHighestDepth());
            }
            var ID = process_mc.getNextHighestDepth();
            var ref_mc = process_mc.createEmptyMovieClip("process" + ID, ID);
            ref_mc.handler = handler;
            ref_mc.scope = scope;
            ref_mc.timeline = timeline;
            ref_mc.frameNumber = frameNumber;
            arguments.shift();
            arguments.shift();
            arguments.shift();
            arguments.shift();
            ref_mc.args = arguments;
            ref_mc.onEnterFrame = function()
            {
                    if(this.timeline._currentframe == this.frameNumber){
                            this.scope[this.handler].apply(this.scope, this.args);
                            this.removeMovieClip();
                    }
            };
            //ref_mc.onEnterFrame(); // just in case already there
    }
    
  • Generic Responder – Good for Command Pattern

    When implementing the Command pattern for this game concept I’m working on at home, I had a need for the command to also support an “executed” method. Typically, it executes, and that’s the end of it.

    However, I’m managing the commands in a Queue/Stack of sorts, and need to know when the command is done. Since the command class really has little coupling with the source that it’s actually calling the command on, I created a Responder class that they all could share. The issue is, however, there is no way to create these in such a way to merely have a method, execute it when the even happens, and then go away.

    Granted, my class could implement the event, and using GDispatcher, execute it, but these events are asyncronous, and I don’t want the command adding himself as a listener to the “receiver”, or the class he’s executing the command on. Everything now is nicely coupled only via methods or explicit setting via the Controller. It’s an abstract pain in the arse, but so far the code is beautiful and flexible. Thus, the Responder needed to have a Singleton’esque ability to create instances of himself for one time uses, but have enough knowledge of the method he’s calling since the class who is using him cares not what even happens to him. The usual way is when you create a responder, you hold onto it, or map it back to yourself; like Remoting/Central responder objects either map to functions in your class or are generic responder objects that execute in your class’ scope. If you don’t care, what do you do?

    I created a static method of my responder class to create one-time event listeners that call a method, pass what args you need, and assumably die when done. This way, my Command class could execute the command, and get the generic responder object as the return value. The receiver, or the class getting the command executed upon it, could return this responder, and when his event is done, merely have the responder inform the command class without having to worry about caring about the responder objects after that point.

    Since the Command class adds himself as a listener, he’ll be able to generate events on when commands are started and stopped (and any number of mods such as “undo” in the future), and this then supports a nice way for the Queue to know wtf is going on.

    Observe the method; the entire class is at the bottom.

    static function createGenericResponder(method:String):Object
    {
            var o:Object = {};
            grantskinner.events.GDispatcher.initialize(o);
            o.method = method;
            o[method] = function()
            {
                    dispatchEvent({type: this.method, target: this, results: arguments});
            };
            return o;
    }
    

    Here’s an example of a function called via the Command class, and the reciever returning the generic responder which he’ll call when an animation is done.

    public function attack(targets_array:Array):Object
    var o:Object = jxl.events.Responder.createGenericResponder("onDoneAttacking");
    this.gotoAndPlay(ATTACKING_START);
    doWhenFrameReached("onDoneAttacking", this, this, ATTACKING_END, o);
    return o;
    }
    

    And the Responder class it sits in:

    class jxl.events.Responder
    {
            static var inited:Boolean;
            
            public var addEventListener:Function;
            public var removeEventListener:Function;
            private var dispatchEvent:Function;
            
            function Responder()
            {
                    if(!inited){
                            inited = true;
                            grantskinner.events.GDispatcher.initialize(Responder.prototype);
                    }
            }
            
            public function onResult()
            {
                    dispatchEvent({type: "result", target: this, results: arguments});
            }
            
            public function onStatus()
            {
                    dispatchEvent({type: "status", target: this, results: arguments});
            }
            
            static function createGenericResponder(method:String):Object
            {
                    var o:Object = {};
                    grantskinner.events.GDispatcher.initialize(o);
                    o.method = method;
                    o[method] = function()
                    {
                            dispatchEvent({type: this.method, target: this, results: arguments});
                    };
                    return o;
            }
    }
    
  • Web Service Connector Factory

    Waiting on Java programmers, so trying to be effective with my time. Figured I’d show some code snippets I’ve found useful over the past couple of weeks. Hopefully someone can gleen some use from ’em.

    First on da platter is a factory function to create web service calls. I had some problems with the web service classes, so ended up using the WebServiceConnector on the majority of my work here at my job. However, as a physical component with a few parameters, I needed an easy way to create many, allow them to function indenpendently, but quickly get the code running so I could meet my Friday deadlines.

    The below creates WebServiceConnectors, initializes them, fires off the web service call, and waits for the response. When there is a response, it calls whatever function is required, and then self-destructs. Who knows if garbage collection cleans up the mess… Make sure you have a WebServiceConnector in your library. Technically the return value should be WebServiceConnector.

    
    function createWebService(WSDLURL,
                              result_str,
                              result_obj,
                              status_str,
                              status_obj,
                              operation,
                              params):Object
    {
            if(wsID == null){
                    wsID = -1;
            }
            wsID++;
            // create the web service connector
            var ws = attachMovie("WebServiceConnector", "ws" + wsID, getNextHighestDepth());
            ws.WSDLURL = WSDLURL;
            
            // create a responder object and set him up with needed supplies
            var r = {};
            // who is my parent?
            r.owner = this;
            // what web service?
            r.ws = ws;
            // what method do I call when done?
            r.result_str = result_str;
            // what scope is he in?
            r.result_obj = result_obj;
            // what method do I call when I flarge up?
            r.status_str = status_str;
            // what scope is he in?
            r.status_obj = status_obj;
            // define my result function
            r.result = function(result)
            {
                    // call my callback, and pass the result
                    this.result_obj[this.result_str](result);
                    this.ws.removeMovieClip();
            };
            r.status = function(status)
            {
                    // call my callback, and pass the status
                    this.status_obj[this.status_str](status);
            };
            // add the responder as a listener
            ws.addEventListener("result", r);
            ws.addEventListener("status", r);
            // define the web service method name
            ws.operation = operation;
            // any web service arguments?
            // Remove the first 5 to check for leftovers...
            arguments.shift();
            arguments.shift();
            arguments.shift();
            arguments.shift();
            arguments.shift();
            if(arguments.length > 0){
                    ws.params = arguments;
            }else{
                    ws.params = [];
            }
            // start this mug!
            ws.trigger();
            // you want this?
            return ws;
    }
    

    Example usage:

    var ws = createWebService("http://something.com/service?WSDL",
                              "result",
                              this,
                              "status",
                              this,
                              "doIt",
                              "JesterXL",
                              "mypassword");
    
  • Super need not apply, nor call

    Dude, is this a bug in AS2? I’m probably doing it wrong.

    In the main timeline, I can do:

    function Mammal(target)
    {
            this.target = target;
    }
    
    function Cow(t)
    {
            super.apply(this, [t]); // doesn't work
            super.apply(super, [t]); // doesn't work
            super.call(this, t); // doesn't work
            super.call(super, t); // doesn't work
    }
    Cow.prototype = new Mammal();
    

    It doesn’t even compile in AS2:

    class Mammal extends Cow
    {
            function Mammal(t)
            {
                    super.apply(this, [t]); // says there is no apply method
                    super.call(this, t); // says there is no call method
            }
    }
    

    I’m guessing this is because inside the constructor, it’s scoped to the function vs. “this”, where this is the class.

    Typically, I’ll do:

    function MyClass()
    {
            init.apply(this, arguments);
    }
    

    So if the init method has a lot of arguments, I don’t have to type them out 3 times; twice in the constructor, and then again in the init. I figured I could just bypass init, and use super… but I guess he’s weird…? I’m confused.