It is beyond anything you have ever experienced or imagined
256 JavaScript Game Extensions
Function#debounce Useful JavaScript Game Extension #36
Nov 27th
I got this from Underscore.js.
###*
Calling a debounced function will postpone its execution until after
wait milliseconds have elapsed since the last time the function was
invoked. Useful for implementing behavior that should only happen after
the input has stopped arriving. For example: rendering a preview of a
Markdown comment, recalculating a layout after the window has stopped
being resized...
lazyLayout = calculateLayout.debounce(300)
$(window).resize(lazyLayout)
@name debounce
@methodOf Function#
@returns {Function} The debounced version of this function.
###
Function::debounce = (wait) ->
timeout = null
func = this
return ->
context = this
args = arguments
later = ->
timeout = null
func.apply(context, args)
clearTimeout(timeout)
timeout = setTimeout(later, wait)Already I can see an important use for it. In the code editor we copy out the buffer every keyup. This can lead to a bunch of extra work for the browser when typing. Usually it’s not a big deal because the files are generally small, but on larger files it can add up and cause some lagging. When using debounce the editor will only trigger after enough milliseconds have elapsed since the end of new keyup events. This will keep the IDE from lagging on larger files while you are typing.
Another place debounce is useful is in a game that implements a Halo style health regeneration. Every time the player takes damage a debounced startRegen function could be called. That way the regen will only start after enough time without taking damage has elapsed. In the game version it would probably be better to constrain it to ticks of the engine, or engine elapsed time for more accuracy.
I’m always a big fan of Function functions, they are a great way to reduce boilerplate and solve higher-order problems.
Array#pipeline Useful JavaScript Game Extension #35
Nov 16th
###*
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 inputThe 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.
JavaScript Number#even and Number#odd, Useful JavaScript Game Extensions #33 and #34
Aug 3rd
Wow, it’s been a while! But enough with the small talk, time for some more simple JavaScript extensions!
###*
Returns true if this number is even (evenly divisible by 2).
@name even
@methodOf Number#
@type Boolean
@returns true if this number is an even integer, false otherwise.
###
Number::even = ->
this % 2 == 0
###*
Returns true if this number is odd (has remainder of 1 when divided by 2).
@name odd
@methodOf Number#
@type Boolean
@returns true if this number is an odd integer, false otherwise.
###
Number::odd = ->
if this > 0
this % 2 == 1
else
this % 2 == -1These are just a couple of simple methods so you can do things like if exponent.even() to make code quite a bit more readable. The only trick is for Number#odd, due to the way the default mod operator works in JavaScript it would be a pain to check if a negative number were odd without this helper.
Stay tuned for the next 222 parts of the series!
Array::eachPair A useful method for interacting each element of an array with another (#32)
Jun 20th
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, bArray#compact Useful JavaScript Game Extension #31
May 10th
###*
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!
Array#extremes Useful JavaScript Game Extension #30
Mar 23rd
###*
* 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: maxUsage:
[-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, 94Array#wrap Useful JavaScript Game Extension #29
Mar 16th
/** * Pretend the array is a circle and grab a new array containing length elements. * If length is not given return the element at start, again assuming the array * is a circle. * * @param {Number} start The index to start wrapping at, or the index of the * sole element to return if no length is given. * @param {Number} [length] Optional length determines how long result * array should be. * @returns The element at start mod array.length, or an array of length elements, * starting from start and wrapping. * @type Object or Array */ Array.prototype.wrap = function(start, length) { if(length != null) { var end = start + length; var result = []; for(var i = start; i < end; i++) { result.push(this[i.mod(this.length)]); } return result; } else { return this[start.mod(this.length)]; } };
Simple use:
[1, 2, 3].wrap(-1) => 3
[1, 2, 3].wrap(6) => 1
Or get fancy and tile your kitchen:
["w", "o", "o", "o"].wrap(0, 16) => ["w", "o", "o", "o", "w", "o", "o", "o", "w", "o", "o", "o", "w", "o", "o", "o"]
Array#clear Useful JavaScript Game Extension #28
Mar 15th
Here’s a useful little method that empties out an array. Sure you could type myArray.length = 0; but that is kind of weird. For some reason myArray.clear() just makes more sense to me.
/** * Empties the array of it's contents. It is modified in place. * * @type Array * @returns this, now emptied. */ Array.prototype.clear = function() { this.length = 0; return this; };
The series continues…
Javascript String#constantize and String#parse – Useful Extensions 26 and 27
Feb 6th
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 thisconstantize 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.
Number#snap Useful JavaScript Game Extension #25
Jan 7th
Well my friends, it’s been quite some time. So without further ado back to the series!
/** * Returns the the nearest grid resolution less than or equal to the number. * * EX: * (7).snap(8) => 0 * (4).snap(8) => 0 * (12).snap(8) => 8 * * @param {Number} resolution The grid resolution to snap to. * @returns The nearest multiple of resolution lower than the number. * @type Number */ Number.prototype.snap = function(resolution) { return (this / resolution).floor() * resolution; };
This handy method is useful for when you need to snap input to a grid (like in a tile editor).
I hope you enjoyed this installment of the wonderful 256 part series on JavaScript game extensions.