Campaigning For Public Office

January 7th, 2012

I want to live in a country where publicly campaigning for political office violates a basic social contract. Where offenders are shamed for participating in a loathsome, detestable activity. Where we view it for what it actually is: a repugnant, self-aggrandizing, borderline narcissistic circus. Where the hyperbolic rhetoric, the media sensationalism, and the pandering to basic human emotions is morally disgusting.

Humans are not biologically evolved to visit Disneyland

January 16th, 2011

One of the perks (or curses, depending on how you look at it) of working for Disney was having a Silver Pass. The Silver Pass entitles employees and three friends or family members to have access to the amusement parks. Whenever friends or family visited me in LA, I usually took them down to Anaheim to spend the day at Disneyland. I went, not because I enjoyed going, because it was a spectacle and it was free. In my three years at Disney, I maybe visited the park over a dozen times. On one of my last trips, I came home, took the obligatory post-Disneyland nap (PDN) and then wrote this.

Humans are not biologically evolved
to visit Disneyland.

At around 4pm in the afternoon,
kids get whiney and annoying,
parents get grumpy.
No one looks happy trying to
maximize their dollar to fun ratio.

The breaking point comes when
fanny packs outnumber smiles.
A long day of waiting is punchuated
by brief moments of forced adrenaline.

Being voluntarily assaulted by bright colors,
the perpetual crescendos of background soundtrack,
as well as resisting a biological fixation on crowds
is exhausting.

Doing the Konami Code with AS3

December 23rd, 2010

For a project I was working on, I wanted to the ability to enter a secret string of keys on the Keyboard (e.g. the Konami code). Here’s the class to be able to do just that.

package
{
    import flash.display.*;
    import flash.ui.*;
    import flash.utils.*;
    import flash.events.*;
   
    /**
    *   This class is for creating secret codes
    *   entered on the keyboard (e.g. Konami Code)
    *   @author Matt Moore matt@cloudkid.com
    */

    public class SecretCode extends EventDispatcher
    {
        /** Event when the code entered has succeeded */
        public static const SUCCESS:String = "onSuccess";
       
        /** Event when the code has been entered bad */
        public static const FAILED:String = "onFailed";
       
        /** Event dispatched when the code listening times out */
        public static const TIMEOUT:String = "onTimeout";
       
        /** We'll save the konami code, this is the default */
        public static const KONAMI:Array = [
            Keyboard.UP, Keyboard.UP,
            Keyboard.DOWN, Keyboard.DOWN,
            Keyboard.LEFT, Keyboard.RIGHT,
            Keyboard.LEFT, Keyboard.RIGHT,
            66, //B
            65, //A
        ];
       
        /** The stage to listen to keystrokes */
        protected var __stage:DisplayObject;
       
        /** The secret code (default here is Konami) */
        protected var __code:Array;
       
        /** The limit input timer, code times out */
        protected var __timeoutTimer:Timer;
       
        /** Record the key inputs */
        protected var __keyRecord:Array = [];
       
        /** Whether this is enabled or not */
        protected var __enabled:Boolean;
       
        /**
        *   Listen for secret codes
        *   @param obj The stage to listen to keystrokes on
        *   @param timeThreshold The number of ms you have to enter the time
        *   @param code The optional array of keyboard inputs to check for
        */

        public function SecretCode(obj:DisplayObject, timeThreshold:int=5000, code:Array=null): void
        {
            __stage = obj;
           
            __code = code == null ? KONAMI : code;
           
            __timeoutTimer = new Timer(timeThreshold, 1);
           
            enabled = true;
        }
       
        /**
        *   Enable or disable this
        */

        public function set enabled(enabled:Boolean): void
        {
            __enabled = enabled;
           
            __timeoutTimer.removeEventListener(TimerEvent.TIMER, onTimeout);
            __stage.removeEventListener(KeyboardEvent.KEY_UP, onCodeInput);
            __stage.removeEventListener(KeyboardEvent.KEY_DOWN, onStartCodeInput);
           
            if (enabled)
            {
                __timeoutTimer.addEventListener(TimerEvent.TIMER, onTimeout);
                reset();
            }
        }
       
        /**
        *   Get the enabled status
        */

        public function get enabled(): Boolean
        {
            return __enabled;
        }
       
        /**
        *   Entering the code has timed out from when you hit the first key
        *   @param ev Timer Event
        */

        private function onTimeout(ev:TimerEvent): void
        {
            dispatchEvent(new Event(TIMEOUT));
            reset();
        }
       
        /**
        *   This resets listening for a code
        */

        private function reset(): void
        {
            __stage.removeEventListener(KeyboardEvent.KEY_UP, onCodeInput);
           
            __stage.removeEventListener(KeyboardEvent.KEY_DOWN, onStartCodeInput);
            __stage.addEventListener(KeyboardEvent.KEY_DOWN, onStartCodeInput);
           
            __keyRecord = [];
            __timeoutTimer.reset();
        }
       
        /**
        *   When the user starts inputting on the keyboard
        *   @param Keyboard event key down
        */

        private function onStartCodeInput(ev:KeyboardEvent): void
        {
            // The first key must be entered correctly to start listening
            if (ev.keyCode != __code[0]) return;
           
            __stage.removeEventListener(KeyboardEvent.KEY_DOWN, onStartCodeInput);
           
            __stage.removeEventListener(KeyboardEvent.KEY_UP, onCodeInput);
            __stage.addEventListener(KeyboardEvent.KEY_UP, onCodeInput);
           
            __timeoutTimer.start();
        }
       
       
        /**
        *   Record the keyboard inputs
        *   @param ev Keyboard event key up
        */

        private function onCodeInput(ev:KeyboardEvent): void
        {
            __keyRecord.push(ev.keyCode);
           
            if (__keyRecord.length < __code.length)
            {
                return;
            }
           
            if (__keyRecord.length > __code.length)
            {
                dispatchEvent(new Event(FAILED));
                reset();
                return;
            }
           
            if (__keyRecord.toString() == __code.toString())
            {
                dispatchEvent(new Event(SUCCESS));
                reset();
                return;
            }
        }
       
        /**
        *   Destroy this class. Don't use after this
        */

        public function destroy(): void
        {  
            __timeoutTimer.removeEventListener(TimerEvent.TIMER, onTimeout);
            __timeoutTimer.reset();
            __timeoutTimer = null;
           
            __keyRecord = null;
            __code = null;
           
            __stage.removeEventListener(KeyboardEvent.KEY_UP, onCodeInput);
            __stage.removeEventListener(KeyboardEvent.KEY_DOWN, onStartCodeInput);
            __stage = null;
        }
    }
}

Here’s an example of implementing the SecretCode object. In the constructor you can pass in your secret code into the constructor as an array of keyCodes. If you don’t specify anything, like below, it uses the Konami Code.

var secret:SecretCode = new SecretCode(stage, 3000);
secret.addEventListener(SecretCode.SUCCESS, onSuccess);

function onSuccess(event:Event): void
{
    trace("You have entered the secret code correctly!");
}

I Have the Best Roommate and Here’s Why

July 11th, 2010

This week, I arrived safely, albeit slight jetlagged, home from my Denver trip. I hadn’t seen my roommate Kathryn in about a week so we played catch-up in the kitchen right before bedtime. We reciprocated stories about our forth of July weekends when, throughout our conversation, we were interrupted by a periodic and faint yelp-squeal.

It sounded like it was coming from the inside of our stove. I crouched down to confirm that it was, in fact, coming from that general vicinity. Kathryn grabbed a headlamp from her room and we both crouched down with one eye to the floor. It was clear that among the thicket of dust balls was a tiny mouse caught in not one, but two traps.

Kathryn removed the drawer from underneath the oven so that we could get a better look at the mouse situation. Awhile ago, our landlord had placed sticky traps under our oven in combination with these black plastic clamp traps. Somehow the mouse had managed to find the only sticky spot not covered in pillowy gray dust while having its hind parts crushed in the clamp.

The terms of Kathryn and I’s contract for what was going to happen next were agreed upon before proceeding. It can be summarized by the following: I was going to owe her one. My role would be to stand with one foot in the kitchen and one in the hallway with a clenched fist near my mouth. Humans have long and tumultuous relationship with mice, so I felt that evolution was clearly defending my cowardice.

While Kathryn and I discussed the soundest course of action she should take, the mouse started chewing its leg in some desperate, last ditch effort to spread vermin blood all over our kitchen floor. We were clearly wasting time. Kathryn found some gloves, a brown paper bag, and a broom. She brushed the mouse and attached traps into the bag, rolled up the top and scurried out the front door. My sigh of relief was interrupted when seconds later she returned with the unopened brown bag.

Kathryn felt guilty for just leaving the yelp-squealing mouse in the trash can. The only decent thing to do was a mercy killing and the cleanest solution was drowning. Kathryn filled a large yogurt container with water and went to the back porch where she apologized profusely before committing our furry foe to a Stoneyfield Farm grave. As the unqualified medical examiner, I came to the back porch to see that there was no movement of the sticky paper.

Kathryn, you are a brave and courageous individual. Thank you. And yes, I owe you one.

Unequivocally Cold

June 17th, 2010

We all live on a silent island. It’s freezing and I shut the windows, but I’m still unequivocally cold. When I feel cold, I hear the reverberating sound of a maternal voice telling me to “put on a sweater”. I don’t even own a sweater.

The mornings are challenging. Someone throwing an iced bucket of pain on my face, and I’m instantly wide awake unable to think about anything except the things I’d soon forget. My mind grasps for a resting spot where I can watch those other memories storm by.

This morning’s restful spot was about how my friend recently said that what I’m feeling “is human”. If being human is what this is, natural selection is a cruel beast. Yet, it’s comforting to think that my genes are controlling me more than my irrational free will.

What is the evolutionary advantage to heartbreak? Does it make sure that we learn to not take love for granted? Does it force us to relentlessly pursue someone who’s not in our best interest? Does it make us hyper-sensitive to the relationships that are undoubtedly meaningful?

Hattie’s Cupcakes

May 18th, 2010

He was already running ten minutes late. His stubble and hair were the worst combination of terrifying and unsightly. If Charlie was going to make it to Hattie’s birthday then he needed to finish piping the red buttercream frosting. Red was Hattie’s favorite color and he promised hand-crafted pastries weeks ago.

He was fifteen minutes late when the last bit of frosting was on. This is getting ridiculous. He surgically placed all of the little treats into a semi-opaque shallow box designed for the singular purpose of hosting a dozen cupcakes. He placed the container inside his bag, careful not to disturb the architecture of the frosting.

In order to not be late, Charlie needed to rush four blocks as fast as he could without running. He clutched the bag to his chest speed-walking while smuggling a confectionery sleeping baby.

Charlie cracked the door to the subway station with one finger and used his right foot for the rest. His frantic, sweaty face looked around for a conveniently absent clock. Keeping the bag level with one hand, he reached for the subway pass in his back pocket. He is interrupted with a stern and deliberate, “Stop!”

A shiny badge and pleated uniform repeats the single word instruction again. In the distance, a chorus of mechanical voices says, “The train is approaching.” Charlie says, “I need to… just… if I could please… my train…” Unaffected, the badge says, “I’m going to have to take a look in your bag.”

Charlie sighs while gingerly extending his bag. The officer snatches the package and drops it onto a white plastic table. The officer shamelessly separates the zipper to reveal a frosting massacre inside the plastic box. Then, in the background Charlie hears, “The doors are about to close.”

Creating and Seamless Audio Stream in AS3

February 18th, 2010

I was frustrated that there was no ActionScript3 equivalent for setting an audio clip to Stream as you can inside of Flash. I wanted to create a seamless audio loop that was synced with a corresponding looping MovieClip. Because the audio never quite lined up on the last frame of the MovieClip inside Flash CS4, there was always an audible seam. I created a class called AudioStreamController which takes a MovieClip and a Sound object as parameters. On ENTER_FRAME the playback of the MovieClip seeks to the frame of the corresponding Sound position (assuming that the MovieClip is roughly the length of your Sound).

package
{
    import flash.events.*;
    import flash.media.*;
    import flash.display.*;
   
    public class AudioStreamController extends EventDispatcher
    {
        /** The sound channel to control sound playback */
        private var __channel:SoundChannel;
       
        /** The sound object */
        private var __sound:Sound;
       
        /** The number of times to loop the animation */
        public var loops:int = 1;
       
        /** The animatino to sync to audio */
        public var __clip:MovieClip;
       
        /** The total number of frames */
        public var __frames:int;
       
        /** The last paused position */
        public var __lastPosition:int;
       
        /**
        *   The purpose of this class is to replicate the syncing that
        *   you can do in Flash using the audio "Stream" setting
        *   @param clip The animation you want to sync
        *   @param sound The sound object you want to play
        */

        public function AudioStreamController(clip:MovieClip, sound:Sound): void
        {
            __sound = sound;
            __clip = clip;
            __frames = clip.totalFrames;
           
            stop();
        }
       
        /**
        *   Start the playback of the audio and listen for new frame enter
        *   to seek to the correct frame of the animation
        */

        public function play(): void
        {
            __channel = __sound(__lastPosition, loops);
            __clip.addEventListener(Event.ENTER_FRAME, update);
        }
       
        /**
        *   Stop and return to the beginning
        */

        public function stop(): void
        {
            if (__channel)
            {
                __channel.stop();
            }
            __lastPosition = 0;
            __clip.gotoAndStop(1);
            __clip.removeEventListener(Event.ENTER_FRAME, update);
        }
       
        /**
        *   Pause the playback and save the current position
        */

        public function pause(): void
        {
            __clip.removeEventListener(Event.ENTER_FRAME, update);
            __lastPosition = __channel.position;
            __channel.stop();
        }
       
        /**
        *   Update event called on entering new frame of the animation
        *   @param ev Enter frame event
        */

        protected function update(ev:Event): void
        {
            // This is the percentage of progress of all the loops
            var percent:Number = __channel.position / (__sound.length * loops);
           
            // The current frame over all the loops
            var f:int = Math.round((__frames - 1) * loops * percent) + 1;
           
            // The current frame gets converted into a frame on a single loop
            f = f - int(f / __frames) * __frames;

            __clip.gotoAndStop(f);

            if (percent > 0.999)
            {
                __clip.removeEventListener(Event.ENTER_FRAME, update);
                __clip.gotoAndStop(__frames);
               
                dispatchEvent(new Event(Event.COMPLETE));
            }
        }
       
        /**
        *   Destroy this controller object
        *   don't use after this point
        */

        public function destroy(): void
        {
            __clip.removeEventListener(Event.ENTER_FRAME, update);
           
            stop();
           
            __clip = null;
            __sound = null;
            __channel = null;
        }
    }
}

Exporting Layers as Separate SWFs

November 16th, 2009

Here’s another JSFL tool I created. This one will save each layer  on the current timeline (there’s also an option to export selected layers) as a separate SWFs. I find this useful for doing a batch process of transparent PNGs into SWFs. I originally made this for my co-worker Evan who uses this to export layers of animation so that he can assemble them in After Effects and manipulate the layers independently (useful for doing things like depth of field, parallax, or setting up 3D scenes). The SWFs that are generated are named according to the layer name (e.g., “my-circle” layer is exported as “my-circle.swf”).

This is Flash CS4-only. Download the extension here and run with the Adobe Extension Manager to install. Restart Flash and run under Commands > Exporting > Export All Layers or Export Selected Layers. This tool is licensed under the MIT license.

Library and Layer Renamer Tool for Flash

November 15th, 2009

I occasionally need to do a lot of renaming in Flash. For instance, you bring in a bunch of PNGs into Flash, distribute them to layers, but want to remove “.png” from their name on each layer. Or, maybe more practically,  you want to rename all your library class names from the package “com.domain.” to “com.anotherdomain.”. Well you’re in luck, because I just created a tool that does just that.

Library and Layer Renamer is a JSFL tool for Flash CS4 only. This tool has two functions (which can be found under the Commands > Utilities menu in Flash). First choose a selection type–for the Library Renamer, you can choose all items, only selected items, or build a selection based on a regular expression (e.g. to match all items with the string “.png” you would type in “\.png” in the text field below “Match Pattern”).

Next, if you’re using the Library Renamer, you can choose what to rename: the base class, the class name, or the library item name. For the Layer Renamer, only the layer name is affected.

Based on the selection, you can add a prefix, suffix, or do a pattern replace.  For instance, if you have five library items ["my clip", "my ball animation", "my graphic", "my button", and "my special something"] and you want to replace the word “my” with “sam’s” in each of those item names, the pattern would be “my” and the replace would be “sam’s”.

Where can you get this wonderful tool? You can download the latest from here. You can install this with the CS4 Extension Manager (a restart of Flash is required). This tool is licensed under the MIT license.

Library Renamer UI Screenshot

Layer Renamer UI Screenshot

Regular Status

July 30th, 2009

Regular status means upon entering a point of service (restaurant, coffee shop) your exact order can be anticipated without any verbal or physical prompting.

My friend Dave Schlafman is the professional at regular status. He has more regular status in the metro Boston-area than anyone I know–probably dozens of restaurants and coffee shops. I’ve known this about him since we were at college together. I believe I have distilled down what exactly are the qualities that make regular status possible using Dave as a test case.

  1. You need to be memorable to the staff who probably sees hundreds of people each day. Options include being: very friendly, neurotic, funny, eccentric.  A consistent visual cue, like wearing the same jacket or hat, certainly would help to make you recognizable.
  2. You need to be original with your order.  Maybe even get something that no one else would order. For instance, at Starbucks Dave’s order goes something like this: “Soy chai latte, five pumps of chai, no water, extra extra extra hot”.
  3. You need to be consistent and order the same thing each time even if it means settling for monotony. Dave is so habitual that he rarely deviates from the one thing he likes.

If you do these three things time after time, I believe you will be able to attain regular status (but probably not as much as Dave).