256 JavaScript Game Extensions

Array#pipeline Useful JavaScript Game Extension #35

###*
Pipe the input through each function in the array in turn. For example, if you have
a list of objects you can perform a series of selection, sorting, and other 
processing methods and then receive the processed list. This array must contain 
functions that accept a single input and return the processed input. The output of
the first function is fed to the input of the second and so on until the final
processed output is returned.
 
@name pipeline
@methodOf Array#
 
@param {Object} input The initial input to pass to the first function in the pipeline.
@returns {Object} The result of processing the input by each function in the array.
###
Array::pipeline = (input) ->
  for fn in this
    input = fn(input)
 
  return input

The main use for this is in the PixieEngine cameras module where we need to process the camera transform with a stream of modifiers. This also allows for the game objects list to be z-sorted, filtered to a subset that passes a clip test, or any other arbitrary stream filter.

I think this is probably some sort of fundamental concept of functional programming, but I’m not sure if `pipeline` is the right name. If anyone has historic info on this please let me know.

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

Array#extremes Useful JavaScript Game Extension #30

###*
 * Returns an object containing the extremes of this array.
 * 
 * @param {Function} [fn] An optional funtion used to evaluate 
 * each element to calculate its value for determining extremes.
 * @returns {min: minElement, max: maxElement}
 * @type Object
### 
Array::extremes = (fn) ->
  fn ||= (n) -> n
 
  min = max = undefined
  minResult = maxResult = undefined
 
  this.each (object) ->
    result = fn(object)
 
    if min?
      if result < minResult
        min = object
        minResult = result
    else
      min = object
      minResult = result
 
    if max?
      if result > maxResult
        max = object
        maxResult = result
    else
      max = object
      maxResult = result
 
  min: min
  max: max

Usage:

[-1, 3, 0].extremes() # => {min: -1, max: 3}

test "#extremes", ->
  array = [-7, 1, 11, 94]
 
  extremes = array.extremes()
 
  equals extremes.min, -7, "Min is -7"
  equals extremes.max, 94, "Max is 94"
 
  extremes = array.extremes (value) ->
    value.mod 11
 
  equals extremes.min, 11
  equals extremes.max, 94

Javascript String#constantize and String#parse – Useful Extensions 26 and 27

Here are two extensions to the String class that I’ve found quite useful. constantize and parse. They are in CoffeeScript because JavaScript fills me with a growing disgust.

String::constantize = () ->
  if this.match /[A-Z][A-z]*/
    eval("var that = #{this}")
    that
  else
    undefined
 
String::parse = () ->
  try
    return JSON.parse(this)
  catch e
    return this

constantize is based on the ActiveSupport method. It transforms a string that represents the name of a class into a reference to that class. It uses eval to accomplish this, but until JavaScript gets more extensive reflection capabilities it’s probably the best we can do.

Parse is a useful way to convert the string into a raw JavaScript type if possible, otherwise it returns just the string itself. For example if I have a string "false", "false".parse() will return the JavaScript value false. Likewise '{"a": 7}'.parse() will return a JavaScript object with a property a that has the value 7.

Pretty sweet.