Support Libraries

animframe.js
(function(){
  window.requestAnimationFrame = window.requestAnimationFrame
  || window.mozRequestAnimationFrame
  || window.webkitRequestAnimationFrame;
  window.cancelAnimationFrame = window.cancelAnimationFrame
  || window.mozCancelAnimationFrame
  || window.webkitCancelAnimationFrame
  || window.webkitCancelRequestAnimationFrame;
  if(!window.requestAnimationFrame){
    var last = 0;
    window.requestAnimationFrame = function(cb,elt){
      var cur = new Date().getTime();
      var step = Math.max(0,16-(cur-last));
      var id = window.setTimeout(function(){cb(cur+step);},step);
      last = cur+step;
      return id
    };
  }
  if(!window.cancelAnimationFrame){
    window.cancelAnimationFrame = function(id){
      clearTimeout(id);
    };
  }
}());
input.js
function InputManager(container) {
  this.events = {};
  this.listen(container);
}
 
if (window.navigator.msPointerEnabled) {
  //Internet Explorer 10 style
  InputManager.prototype.eventTouchstart    = "MSPointerDown";
  InputManager.prototype.eventTouchmove     = "MSPointerMove";
  InputManager.prototype.eventTouchend      = "MSPointerUp";
} else {
  InputManager.prototype.eventTouchstart    = "touchstart";
  InputManager.prototype.eventTouchmove     = "touchmove";
  InputManager.prototype.eventTouchend      = "touchend";
}
 
InputManager.prototype.on = function (event, callback) {
  if (!this.events[event]) {
    this.events[event] = [];
  }
  this.events[event].push(callback);
};
 
InputManager.prototype.emit = function (event, data) {
  var callbacks = this.events[event];
  if (callbacks) {
    callbacks.forEach(function (callback) {
      callback(data);
    });
  }
};
 
InputManager.prototype.listen = function (container) {
  if (!container.addEventListener) return;
  var self = this;
 
  var map = {
    39: 1, // Right
    38: 3, // Up
    37: 5, // Left
    40: 7, // Down
    75: 0, // K
    76: 1, // L
    79: 2, // O
    73: 3, // I
    85: 4, // I
    74: 5, // J
    77: 6, // M
   188: 7, // ,
   190: 8, // .
    83: 0, // S
    68: 1, // D
    69: 2, // E
    87: 3, // W
    81: 4, // Q
    65: 5, // A
    90: 6, // Z
    88: 7, // X
    67: 8, // C
   101: 0, // KP5
   102: 1, // KP6
   105: 2, // KP9
   104: 3, // KP8
   103: 4, // KP7
   100: 5, // KP4
    97: 6, // KP1
    98: 7, // KP2
    99: 8  // KP3
  };
 
  var keyRepeatTime = [0,0,0,0,0,0,0,0,0];
 
  document.addEventListener("keydown", function (event) {
    var modifiers = event.altKey || event.ctrlKey || event.metaKey ||
                    event.shiftKey;
    var mapped    = map[event.which];
 
    if (!modifiers) {
      if (mapped !== undefined) {
        event.preventDefault();
        if (event.timeStamp - keyRepeatTime[mapped] >= 330) {
          self.emit("move", mapped);
          keyRepeatTime[mapped] = event.timeStamp;
        }
      }
    }
  },false);
  document.addEventListener("keyup", function (event) {
    var mapped   = map[event.which];
    if (mapped !== undefined) {
      keyRepeatTime[mapped] = 0;
    }
  },false);
 
  if (!window.navigator.msPointerEnabled) {
 
    if (container.setCapture) {
 
      container.addEventListener("mousedown", function (event) {
        var modifiers = event.altKey || event.ctrlKey || event.metaKey ||
                        event.shiftKey;
        if (!modifiers && event.button===0) {
          event.preventDefault();
          var clickRepeatTime = null;
          var where = {
                      x:event.clientX-container.getBoundingClientRect().left,
                      y:event.clientY-container.getBoundingClientRect().top
                      };
          var clickRepeatFunc;
          clickRepeatFunc = function () {
              self.emit("click", where);
              clickRepeatTime = window.setTimeout(clickRepeatFunc, 330);
          };
          var clickMouseMoveFunc = function (event) {
            where.x = event.clientX-container.getBoundingClientRect().left;
            where.y = event.clientY-container.getBoundingClientRect().top;
          };
          var clickMouseUpFunc;
          clickMouseUpFunc = function (event) {
            if (event.button=== 0) {
              if (clickRepeatTime)
                window.clearTimeout(clickRepeatTime);
              clickRepeatTime = null;
              container.removeEventListener("mousemove", clickMouseMoveFunc, false);
              container.removeEventListener("mouseup", clickMouseUpFunc, false);
            }
          };
          container.addEventListener("mouseup", clickMouseUpFunc,false);
          container.addEventListener("mousemove", clickMouseMoveFunc, false);
          container.setCapture();
          clickRepeatFunc();
        }
      },false);
 
    } else {
 
      container.addEventListener("mousedown", function (event) {
        var modifiers = event.altKey || event.ctrlKey || event.metaKey ||
                        event.shiftKey;
        if (!modifiers && event.button===0) {
          event.preventDefault();
          var clickRepeatTime = null;
          var where = {
                      x:event.clientX-container.getBoundingClientRect().left,
                      y:event.clientY-container.getBoundingClientRect().top
                      };
          var clickRepeatFunc;
          clickRepeatFunc = function () {
              self.emit("click", where);
              clickRepeatTime = window.setTimeout(clickRepeatFunc, 330);
          };
          var clickMouseMoveFunc = function (event) {
            where.x = event.clientX-container.getBoundingClientRect().left;
            where.y = event.clientY-container.getBoundingClientRect().top;
          };
          var clickMouseUpFunc;
          clickMouseUpFunc = function (event) {
            if (event.button=== 0) {
              if (clickRepeatTime)
                window.clearTimeout(clickRepeatTime);
              clickRepeatTime = null;
              window.removeEventListener("mousemove", clickMouseMoveFunc, false);
              window.removeEventListener("mouseup", clickMouseUpFunc, false);
            }
          };
          window.addEventListener("mouseup", clickMouseUpFunc,false);
          window.addEventListener("mousemove", clickMouseMoveFunc, false);
          clickRepeatFunc();
        }
      },false);
 
    }
 
  }
 
  // Listen to swipe events
  var touchStartClientX, touchStartClientY;
 
  container.addEventListener(this.eventTouchstart, function (event) {
    if (( !window.navigator.msPointerEnabled && event.touches.length > 1) || event.targetTouches > 1) return;
 
    if(window.navigator.msPointerEnabled){
        touchStartClientX = event.pageX;
        touchStartClientY = event.pageY;
    } else {
        touchStartClientX = event.touches[0].clientX;
        touchStartClientY = event.touches[0].clientY;
    }
 
    event.preventDefault();
  },false);
 
  container.addEventListener(this.eventTouchmove, function (event) {
    event.preventDefault();
  },false);
 
  container.addEventListener(this.eventTouchend, function (event) {
    if (( !window.navigator.msPointerEnabled && event.touches.length > 0) || event.targetTouches > 0) return;
 
    var touchEndClientX, touchEndClientY;
    if(window.navigator.msPointerEnabled){
        touchEndClientX = event.pageX;
        touchEndClientY = event.pageY;
    } else {
        touchEndClientX = event.changedTouches[0].clientX;
        touchEndClientY = event.changedTouches[0].clientY;
    }
 
    var dx = touchEndClientX - touchStartClientX;
    var dy = touchStartClientY - touchEndClientY;
 
    if (Math.abs(dx) < 10) {
      if (Math.abs(dy) >= 10)
        self.emit("move", dy>0 ? 3 : 7);
      else
        self.emit("click", {
          x:touchEndClientX-container.getBoundingClientRect().left,
          y:touchEndClientY-container.getBoundingClientRect().top
        });
    } else {
      var slope = Math.abs(dy/dx);
      if (slope > 2.0)
        self.emit("move", dy>0 ? 3 : 7);
      else if (slope < 0.5)
        self.emit("move", dx>0 ? 1 : 5);
      else
        self.emit("move", dy>0 ? (dx>0 ? 2 : 4) : (dx<0 ? 6 : 8));
    }
  },false);
 
};
 
InputManager.prototype.restart = function (event) {
  event.preventDefault();
  this.emit("restart");
};