Thursday, May 15, 2014

The making of my Rummy game

Most good developers have at some time in their life created a game.  I decided I wanted to join that group so I set out to make something.

While a scroller could provide some problems I haven't solved before, or something 3D could give me an opportunity to use WebGL, I ultimately landed on a simple rummy card game.

My first draft used Canvas with GSAP, which worked well.  However I eventually found it is hard to determine what elements were clicked on when everything is drawn to canvases.  So... I reverted back to plain HTML and CSS transitions/transforms.

I also took the opportunity to write it with purely functional vanilla JavaScript.  In the past with anything of much complexity I always fell back to my OOP roots, but this worked well.

Something unique to this game is that the entire state is always saved in localStorage so anytime you navigate away from the page, you can navigate back and everything will be exactly as it was left.

So, here is my rummy game ( https://iambrandonn.github.io/rummy/ ).

Monday, February 18, 2013

The new Web Speech API => a Flash Cards Application!

In the last couple of months I've been helping my daughter memorize her multiplication and division tables.  To help her get faster we've used traditional flash cards, which work pretty well.  One day I thought to myself "a computer could easily listen to a student's voice and show appropriate cards...  it could even keep score."  I looked around to see if there were any JavaScript libraries that worked with the microphone to provide speech recognition, but didn't find anything worthwhile.  The best I could get was to use Emscripten to port a C library.  I put it on the back burner and worked on some other things for awhile.  

Then I saw a post about Google Chrome version 25.  In it is implemented the new Web Speech API.  HTML5Rocks did an article covering some of the capabilities here.  In short, the API allows you to add speech recognition to your apps!  Just what I needed!

So off to work on the app...  The API is pretty simple.  These are the steps to use it:
  1. You create an instance of the object, via new webkitSpeechRecognition()
  2. Set continuous to true or false to specify whether it should stop after giving a result or keep listening continuously.
  3. Set interminResults to true or false to specify if you want only the final result or all results.
  4. Provide callbacks via onstart, onresult, onerror, and onend.
I hooked it all up and built the application around it.  I think it turned out pretty well.  I use localStorage to track high scores and store custom lists.

For the main page I went Vanilla JS (well almost... I used the Handlebars VM for templates). So the page has a pretty light footprint (35k).  And 15k of that is Google Analytics, so the actual application code (including the Handlebars VM)  is only 20k.  My experience is that Vanilla JS is a little harder than typical jQuery, Backbone, etc... but it is definitely light and fast.  

Anyway... here's the link to the app:  https://iambrandonn.github.io/FlashCards/

Have fun!

Saturday, October 20, 2012

Keeping Your Knowledge Current

Lately I've been part of several discussions about keeping our tech skills up to date.  This post discusses my techniques for staying current.
  • Commit to spending time EVERY workday (and often non-workdays) keeping up with things. Everyone feels pressure to complete current projects on time... but we can't let that get in the way of maintaining our competency.  I personally spend one to two hours every day scanning various communities and investigating new things.  As a worker in the tech industry you can coast for awhile on your current knowledge, but soon you'll be wasting your time and the resources of your employer using old methods and technologies.
  • There are new libraries and technologies released daily.  Here is how I evaluate whether one is worth my time or not.
    • The easiest way is to watch how frequently it is mentioned.  If it's mentioned only once and not heard about again... don't waste your time.  If you hear about it over and over from multiple sources, especially over an extended period of time, you better check it out.
    • If you decide to investigate it, search for the "main" page about it.  Usually this is the product or project home page.  That should give you a quick idea of what it is about.  In your mind compare it to other similar products.  If it looks like something that may take off, read through the sites tutorials if they exist.  Also check for other blogs/sites with tutorials or discussions on it.  I usually put a product into one of three categories at this point.
      • This is cool! - I need to try out some actual code in the next couple days.
      • Interesting - Ok... I learned what it is.  I have that frame of reference.  Now I will wait to see if it catches on or not.  If so, I'll invest more time at that point.  
      • Redundant or not useful - Don't waste any more time on it.
  • I encourage you to find your own sources of the latest news and trends.  I have three main sources:
    • Hacker News - I subscribe to their RSS feed so I see every post, but if you are short on time just check their home page a couple times a day.  The most useful articles will float to the top.  Some people instead prefer reddit
    • Twitter - I was a latecomer to Twitter.  I still don't tweet much, but I have found it invaluable as a tool to follow some of the influential people in the industry.  (FYI... if someone consistently tweets irrelevant things that pollute my stream, they're gone.  Even if they occasionally post something great, I can't waste my time reading what they had for breakfast.)  This is who I follow.  I particularly recommend:
    • RSS feeds - I use Google Reader.  Here are the tech feeds I follow (probably too much for some).
Some people go to tech conferences as a way to stay current.  In my thinking you are WAY too slow if you are doing most of your learning at conferences.  That means someone else already investigated it, learned about it, prepared/submitted a talk on it, got accepted, and is now giving a talk on it.  That's often a six month or more lag. Ouch.

Employees in our industry are in high demand and we are usually paid well and have employment opportunities across the country.  Staying current is a small investment that justifies that luxury.

What are your tips for staying current?

Monday, October 1, 2012

Color Cam

Last week I had another idea for a crazy webcam oriented experiment.  I imagined a site that played music and showed the video from the webcam.  A technique to determine movement would be used, similar to what WebcamSwiper does.  The movement would be shown as random colors splashes with the intensity/brightness varying based on the volume of the music.  It seemed like it would be kinda psychedelic, but cool.
Well, I finished it.  Here.  It's not bad... but didn't turn out as cool as I thought.  Oh well, moving on.

Monday, September 24, 2012

Webcam Swiper


I've spent a little time lately working on an experiment that uses the new getUserMedia() method.  I'm calling it the Webcam Swiper.  Chrome and Firefox now support Webcam access, although Firefox < 20 requires turning on a flag in about:config.

It's a page that displays a book.  If you allow webcam access it will watch for you swiping your hand left or right through the air, which triggers a page turn in the appropriate direction.

I was inspired to try this when I saw the cool Magic Xylophone.  I thought of all the cases where someone might want to make a simple directional gesture and have something happen on the page.  Image Carousels could rotate, the next item in a list could be displayed, book pages could be turned, etc...

To implement this I had to figure out how to detect when a hand had moved from one side of the screen to the other. I started by detecting motion the same way that the Magic Xylophone does. First turn the image from the webcam to greyscale so I only have to worry about brightness and not color changes. Then, comparing one frame to the next, watch for any pixels that change intensity more than some given threshold.  Next I determine what I call the "motion weight" for the given frame. Basically any pixel on the left side of the screen which is considered to have movement, subtracts from the weight. Any pixel on the right side of the screen which has movement adds to the weight. Total them all up and we get a number that summarizes where the most movement is occurring on the screen. Now all we need to do is compare the "motion weight" over the last series of frames. If we have a highly negative weight which then quickly shifts to a highly positive weight, we know the user just swiped right. If it is positive and goes negative, the user just swiped left. A custom event is fired on the body element of the page. Then whoever is listening for the event can do whatever they want.  In my case I do a couple CSS transitions and transforms to turn the page of the book.

That's all there is to it. I had some problems with varying light level, so I sample every 50 frames and calibrate the sensitivity based on the ambient light level in the room. Also I adjust for slower hardware by timing each frame analysis. If it is taking too long I lower the scan frequency. Otherwise it stays high.

I've made this all into a library which should be fairly easy to use.

Include the webcam-swiper-0.1.js with a script tag or the loader of your choice.

Then bind the swipe events however you choose.  Example with jQuery:


  $("body").bind("webcamSwipeLeft", yourLeftEventHandler);
  $("body").bind("webcamSwipeRight", yourRightEventHandler);

Start the webcam access with a call to the global initializeWebcamSwiper function like this:


  window.initializeWebcamSwiper();

Now it is running!  If you choose to stop it call

  window.destroyWebcamSwiper();

Play with it and feel free to improve it or give any feedback.

Thursday, November 24, 2011

Local Variables and Variable Hoisting

The other day I ran across a few interesting features of JavaScript variable scopes.  Consider this code:


function doSomething({
    var 1;
    if (true{
        var 2;
        alert(a);
    }
    
    alert(a);
}

doSomething();



What would you expect?  If you are used to coding in a C like language, you would expect the first alert to be 2 and the second to be 1.  In JavaScript however this is not the result.  We get 2 for both alerts.  How come?


It turns out that JavaScript has no concept of "block-level" scoping (specific to the if block in this example).  Variables are either globally scoped or they are function scoped.  That means that even though we are in an if-block, we are still using the same scope as we were before entering the block.  So in our example the variable "a" is re-declared and assigned to 2, and it continues to be in scope after leaving the function, and will still be available until the function ends.


Here is a jsFiddle if you would like to play with it.


Reading about this led me to another interesting topic concerning variable scopes.  Look at this code:


1;
function doSomething({
    alert(a);
    var 2;
    alert(a);
}

doSomething();



To start we have a global variable named a which is assigned the value of 1.  Then when doSomething is called the alert displays the global variables value, a function level variable is created and assigned 2, which is then alerted.  Right?  Nope...


The first alert displays "undefined" while the second is 2.  Why doesn't the first fall back to the global variable?  This is due to the way JavaScript handles declarations.  They are automatically "hoisted" to the top of the function, leaving code that looks would look like this:


1;
function doSomething({
    var a;

    alert(a);
    2;
    alert(a);
}

doSomething();




Now it makes sense why we would get an "undefined".  The function scoped variable is completely hiding the global one, and it hasn't been assigned yet.  This is an important point... declarations are hoisted but assignments are not.  


Again, here is a jsFiddle with the scenario.  


Ben Cherry also has a good blog post about this issue.  






Wednesday, November 2, 2011

The debugger statement

The debugger statement in JavaScript will cause a debugger (like FireBug or the Chrome developer tools) to pause execution just as if there was a breakpoint at that line.  This is most useful when you have dynamically generated code or whenever you don't have a chance to set a breakpoint on a line before the code executes.  

Simple example:
var a = 44;
debugger;
alert(a);

In this case the debugger (if open) will pause before the alert is shown.  

Here are the MDN docs for the debugger statement.