Operator Overloading in PaperScript

I was looking into how paper.js did their operator overloading and what I found was pretty clever:

var operators = {
  '+': 'add',
  '-': 'subtract',
  '*': 'multiply',
  '/': 'divide',
  '%': 'modulo',
  '==': 'equals',
  '!=': 'equals'
};

function $eval(left, operator, right) {
  var handler = operators[operator];
  if (left && left[handler]) {
    var res = left[handler](right);
    return operator == '!=' ? !res : res;
  }
  switch (operator) {
  case '+': return left + right;
  case '-': return left - right;
  case '*': return left * right;
  case '/': return left / right;
  case '%': return left % right;
  case '==': return left == right;
  case '!=': return left != right;
  default:
    throw new Error('Implement Operator: ' + operator);
  }
};

Though technically this is PaperScript and not JavaScript, so they can get around the lack of native JS operator overloading. The PaperScript code is given a minimal compile pass which replaces calls to arithmetic operators with calls to $eval().

// PaperScript
var p = new Point(10, 20);
var r = p * 5;

// JavaScript
var p = new Point(10, 20);
var r = $eval(p, "*", 5);

Related PaperScript source

So as long as Point#multiply is defined then the operator is effectively overloaded.

I’m very interested in the implications for PixieEngine and CoffeeScript.

Array::eachPair A useful method for interacting each element of an array with another (#32)

I’ve got this classic n2 collision detection code and I wanted to separate out all the iteration business into its own place. So I spent a long time trying to figure out the name for the method, searching around in case anyone had anything similar. I finally found it each_pair, which is exactly what I wanted. The each implies iteration, and we are iterating over each possible pair of items from the array.

###*
Call the given iterator once for each pair of objects in the array.

Ex. [1, 2, 3, 4].eachPair (a, b) ->
  # 1, 2
  # 1, 3
  # 1, 4
  # 2, 3
  # 2, 4
  # 3, 4

@name eachPair
@methodOf Array#
@param {Function} iterator Function to be called once for
each pair of elements in the array.
@param {Object} [context] Optional context parameter to be
used as `this` when calling the iterator function.
###
Array::eachPair = (iterator, context) ->
  length = this.length
  i = 0
  while i < length
    a = this[i]
    j = i + 1
    i += 1

    while j < length
      b = this[j]
      j += 1

      iterator.call context, a, b

The Advantage of Code Based Game Development Environments

Game development environments that leverage graphical interfaces and parameterized editors are interesting. They have the ability to lower the bar required to get a game up and running without making serious mistakes or getting lost in dead ends. Therefore they are a valuable tool in broadening the population of game developers.

However, there always remains the need for the capability to drop into the source code and edit the algorithms directly. Data structures and algorithms are what software is made of, and if our only interface into game creation is a parameterized editor where we can only configure values, then it will prevent breakthroughs just as much as it prevents failures and dead ends. This is why that no matter how many wizards, GUI tools, application builders, etc. that we have, we must always be able to go to the source and edit.

True progress is born from changing the paradigm, not changing the parameters.

Some of my Favorite Contrasaurus Comments

one of the STUPIDEST games i have ever wasted 5 minutes beating…. and OMFG! 3700 BC? are you f*cking kidding me? the T-rex lived in the CRETACEOUS period. (between 85 and 65 million years ago) You really believe that T-Rex was still around in the Minoan’s discovered bronze? – anonymous

Dear anonymous, if that is your real name… It is a well known FACT that the MODERN TIME MACHINE (circa 1984) is only capable of travelling within a several thousand year range, so explain THAT. How can a DINOSAUR be brought into the FUTURE if it lived millions of years BEYOND THE RANGE OF TIME TRAVEL? – Yahivin

Better window.requestAnimationFrame Shim

There’s been quite a bit of copy/pasting of the compatibility shim for requestAnimationFrame going around on the Net, which is all fine and dandy, but sadly the popular shim isn’t compatible with passing in the timestamp on the setTimeout fallback.

Here’s the improved one:

window.requestAnimationFrame ||=
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame    ||
  window.oRequestAnimationFrame      ||
  window.msRequestAnimationFrame     ||
  (callback, element) ->
    window.setTimeout( ->
      callback(+new Date())
    , 1000 / 60)

Also, a JavaScript version for those of you who have suffered the misfortune of not choosing to use CoffeeScript.

window.requestAnimationFrame || (window.requestAnimationFrame =
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame    ||
  window.oRequestAnimationFrame      ||
  window.msRequestAnimationFrame     ||
  function(callback, element) {
    return window.setTimeout(function() {
      callback(+new Date());
  }, 1000 / 60);
});

Take notice of the param passed to the callback +new Date(). It’s the timestamp that leading implementations pass in.

It has also been rumored that Chrome10 doesn’t pass in the timestamp either, so for super reliability you’ll want to have timestamp ||= +new Date() as the first line of your callback as well.

There were also several issues mentioned in this gist which have not been decisively resolved, so any feedback is certainly welcome. I also decided to just polyfill that ‘ish, because it seems legit enough.

Good luck and Godspeed.

Array#compact Useful JavaScript Game Extension #31

###*
Returns a copy of the array without null and undefined values.

@name compact
@methodOf Array#
@type Array
@returns An array that contains only the non-null values.
###
Array::compact = ->
  this.select (element) ->
    element?

This array compact method is pretty useful. Prototype.js got it from Ruby and I got it from both. Now it’s a proud member of my CoffeeScript corelib.

Not much interesting behavior wise, but one thing to take note of is how short and sweet the code is thanks to using CoffeeScript.

31 down, 225 to go. Peace!

LiveEdit

You know those edit in place plugins for jQuery? Well I couldn’t find any that met these two criteria:

  1. Work on elements not yet in the DOM
  2. Didn’t post anything to the server

Now the first requirement probably makes a lot of sense to you, but I bet you’re wondering about the second one. In these crazy mixed up times with rich HTML5 apps, I don’t want to post to the server often. Maybe I’m using local storage, or perhaps I just want to send a big heap of JSON now and again, but I definitely don’t want to post every time anyone changes the value of an editable field.

So after examining all the terrible options (classic first step when choosing jQuery plugins) I decided to throw my own terrible option into the mix.

(($) ->
  $.fn.liveEdit = () ->
    this.live 'dblclick', () ->
      $this = $(this)

      return if $this.is("input")

      textInput = $("",
        class: $this.attr("class")
        "data-origType": this.tagName
        id: if id = $this.attr("id") then id else null
        type: "text"
        value: $.trim($this.text())
      )

      $this.replaceWith textInput

      textInput.focus().select()

    this.live 'blur keydown', (event) ->
      if event.type == "keydown"
        return unless event.which == 13 || event.which == 9

      $this = $(this)

      return if $this.data("removed")
      return unless $this.is("input")

      $this.attr("data-removed", true)

      $this.replaceWith $("",
        class: $this.attr("class")
        id: if id = $this.attr("id") then id else null
        text: $this.val()
      )

    return this

)(jQuery)

There are two tricks here. The first is that this plugin is really a macro that makes two calls to live. The second is that the editable content keeps it’s same id and class when switched out to a text field, so as long as your selector is not based on the element type it will work. There’s plenty of room for improvements, but this is a super simple first step that meets my needs. Enjoy!

jQuery Plugin: TakeClass

This comes up all the time, you have an element, and you want to select it to be the sole active element from among it’s siblings. With jQuery that is simple enough:

element.addClass("active").siblings().removeClass("active")

Though it is not as simple as it can be and it also fails to chain well. The solution is a super simple jQuery plugin:

(($) ->
  $.fn.takeClass = (name) ->
    this.addClass(name).siblings().removeClass(name)

    return this
)(jQuery)

Now you can really go nuts!

newElement.appendTo(layerSelect).takeClass("active").find(".name").mousedown()

Optimizing JSDoc Toolkit for Large JS Files

Recently I was running into a problem with JSDock Toolkit where it would throw an error saying js: exception from uncaught JavaScript throw: java.lang.OutOfMemoryError: Java heap space.

The solution was to add the -s flag so that it would not try and generate a large, marked-up source file for viewing with the docs.

java -jar jsdoc-toolkit/jsrun.jar jsdoc-toolkit/app/run.js gamelib.js -d=docs -n -s

I also added the -n flag to prevent it from documenting methods that didn’t have comments, such as minified jQuery or Box2d, though this was irrelevant in preventing the js: exception from uncaught JavaScript throw: java.lang.OutOfMemoryError: Java heap space error.