Useful JavaScript Game Extensions: Number#round

Part 13

Here’s another small one, in the same vein as yesterday’s. When you can take for granted that numbers behave as objects, it really cleans up unnecessary references to static Math methods and extra helper methods.

/**
 * @returns The number rounded to the nearest integer.
 *
 * (4.5).round(); // => 5
 * (4.4).round(); // => 4
 */
Number.prototype.round = function() {
  return Math.round(this);
};

Take a look back at the original useful JavaScript game extension Number#Clamp. Though global helper functions have the same number of semantic elements, I find that it’s easier to break down in my head if they are attached to objects. Also, the order of the parameters may be more obvious if you reduce it from 3 to 2.

Useful JavaScript Game Extensions: Number#sign and Number#abs

Part 11 and 12

In an object oriented perspective it can be useful to think of numbers as objects. Why have to deal with “everything is an object, except numbers, those are different and require special methods”, when you can have a more consistent programing environment where numbers are objects too, and have the same interfaces and methods you’d expect.

JavaScript’s prototype based inheritance is perfect for extending the behavior various types of objects, and fortunately for us, unlike in Java, in JavaScript numbers really are objects. Though unfortunately for us, as is usual in JavaScript, the API is seriously lacking.

Getting the sign of a number can often be useful in games. For example, I wanted to have camera tracking where the camera would look ahead by the square of the velocity of the object. But if the object were moving in the negative direction the squaring would obliterate the sign. Number#sign to the rescue!

/**
 * @returns The sign of this number, 0 if the number is 0.
 */
Number.prototype.sign = function() {
  if(this > 0) {
    return 1;
  } else if (this < 0) {
    return -1;
  } else {
    return 0;
  }
}

// Example, using the sign to maintain direction when squaring
var weightedX = dinoPosition.x + (1.25 * dinoVelocity.x * dinoVelocity.x * dinoVelocity.x.sign());

Another useful number method is abs. Why do you need some external object to get the absolute value of a number? Shouldn’t a number know it’s own absolute value? Now they can:

/**
 * @returns The absolute value of the number.
 */
Number.prototype.abs = function() {
  return Math.abs(this);
};

I’m not always against the prototype feature of JavaScript, just against using prototype based inheritance to simulate class and module based inheritance. Stick around towards the end of the series to see some great examples.

See you next time!

Useful JavaScript Game Extensions: Array#first and Array#last

Part 9 and 10 of 256: Array#first and Array#last

The first and last methods of array objects provide a nice semantic wrapper for the concepts. They aren’t really a big time saver, though it is probably very slightly easier to type first than [0]. It is also fairly uncommon to need these methods with much regularity, but when you do need them it’s nice to have them.

/**
 * Returns the first element of the array, undefined if the array is empty.
 *
 * @returns The first element, or undefined if the array is empty.
 * @type Object
 */
Array.prototype.first = function() {
  return this[0];
};

/**
 * Returns the last element of the array, undefined if the array is empty.
 *
 * @returns The last element, or undefined if the array is empty.
 * @type Object
 */
Array.prototype.last = function() {
  return this[this.length - 1];
};

Useful JavaScript Game Extensions Part 8, Number#mod

Part 8/258 Number#mod

For some bizarre reason, JavaScript does not constrain the result of the % operator to be between 0 and the base. This can make computing the index into an array or “wrapping” a negative number a small pain. This method gives all numbers an improved mod method that will guarantee they end up inside the array.

/**
 * A mod method useful for array wrapping. The range of the function is
 * constrained to remain in bounds of array indices.
 *
 * Example:
 * (-1).mod(5) === 4
 *
 * @param {Number} base
 * @returns An integer between 0 and (base - 1) if base is positive.
 * @type Number
 */
Number.prototype.mod = function(base) {
  var result = this % base;

  if(result  0) {
    result += base;
  }

  return result;
};

This makes jumping into an index much easier.

// Example usage
var result = array[n.mod(array.length)];

Though still not quite as nice as in Ruby where you can do:

result = array[n] # Ruby cares enough to make it happen

I love Ruby…

Useful JavaScript Game Extensions: Array#shuffle

Do the shuffle! Array#shuffle

Part 7/256

Shuffling is important, especially in card games.

/**
 * Returns a new array with the elements all shuffled up.
 *
 * @returns A new array that is randomly shuffled.
 * @type Array
 */
Array.prototype.shuffle = function() {
  var shuffledArray = [];

  this.each(function(element) {
    shuffledArray.splice(rand(shuffledArray.length + 1), 0, element);
  });

  return shuffledArray;
};

Notice how building on the previous components of rand and each makes this method much easier to write. You’ll find that when you surround yourself with great APIs things constantly become easier and easier, whereas when you are surrounded with terrible APIs things become harder and harder.

Useful JavaScript Game Extensions: Array#each

Computer code vortex

Welcome to the nether realm of JavaScript extensions… things that should exist and sometimes kind of do, but with a different name and an inconsiderate API.

Part 6 of 256 Useful JavaScript Extensions Array#each.

/**
 * Call the given iterator once for each element in the array,
 * passing in the element as the first argument, the index of
 * the element as the second argument, and this array as the
 * third argument.
 *
 * @param {Function} iterator Function to be called once for
 * each element in the array.
 * @param {Object} [context] Optional context parameter to be
 * used as `this` when calling the iterator function.
 *
 * @returns `this` to enable method chaining.
 */
Array.prototype.each = function(iterator, context) {
  if(this.forEach) {
    this.forEach(iterator, context);
  } else {
    var len = this.length;
    for(var i = 0; i < len; i++) {
      iterator.call(context, this[i], i, this);
    }
  }

  return this;
};

You’ll notice that this method makes use of the possibly existing Array#forEach method if it exists. In fact it is almost an alias of it, but since forEach always returns undefined like a jerk, we need to wrap it and return the object for chaining like a good citizen. Also, who wants to always be writing forEach, why not just each? Yeah… I like this.

// Example:

var people = [{name: "David"}, {name: "Joe"}, {name: "Gandalf"}];

// Greet each person by name
people.each(function(person) {
  alert("Hi " + person.name + "!");
});

Useful JavaScript Extensions: Number#times

Part 5/256

For loops… I hate them so much. Fortunately, a well established functional iteration convention is the Number#times method.

/**
 * Calls iterator the specified number of times, passing in a number of the
 * current iteration as a parameter. The number will be 0 on first call, 1 on
 * second call, etc.
 *
 * @param {Function} iterator The iterator takes a single parameter, the number
 * of the current iteration.
 * @param {Object} [context] The optional context parameter specifies an object
 * to treat as this in the iterator block.
 *
 * @returns The number of times the iterator was called.
 */
Number.prototype.times = function(iterator, context) {
  for(var i = 0; i < this; i++) {
    iterator.call(context, i);
  }
  return i;
}

This hides the inner workings of the iteration from the calling code so there’s no need to keep track of an external dummy iterator variable if you don’t want to.

var n = 3;

// Greets you three times, with respect
n.times(function() {
  alert("O HAI!");
});

// logs: 0, 1, 2
n.times(function(i) {
  console.log(i);
});

Useful JavaScript Game Extensions: Array#remove

Debris Removal
Part 4: Array#remove

JavaScript Arrays are missing some very common, very useful functions. One of those is the remove method. We want to be able to say “Hey you, array, remove this object from yourself! Now!!” But our poor JS array’s don’t know how. They can barely remove elements from specific indices, let alone a specified object. Well no longer! Now they’ll do what we say.

/**
 * Remove the first occurance of the given object from the array if it is
 * present.
 *
 * @param {Object} object The object to remove from the array if present.
 * @returns The removed object if present otherwise undefined.
 */
Array.prototype.remove = function(object) {
  var index = this.indexOf(object);
  if(index >= 0) {
    return this.splice(index, 1)[0];
  } else {
    return undefined;
  }
};

By building off of the Array‘s built in methods we can keep this code very short. We find the first occurrence of the specified object using indexOf, then we remove and return it using splice. If it wasn’t found we return undefined instead.

// An illustrative test suite

test("Array#remove", function() {
  ok([1,2,3].remove(2) === 2, "[1,2,3].remove(2) === 2");
  ok([1,3].remove(2) === undefined, "[1,3].remove(2) === undefined");
  ok([1,3].remove(3) === 3, "[1,3].remove(3) === 3");

  var array = [1,2,3];
  array.remove(2);
  ok(array.length === 2, "array = [1,2,3]; array.remove(2); array.length === 2");
  array.remove(3);
  ok(array.length === 1, "array = [1,3]; array.remove(3); array.length === 1");
});

John Resig has another take on Array#remove, remove by index. You may want to take a look at that as well, though for me it feels more natural to remove by specified object rather than by specified index.

Useful JavaScript Game Extensions: Array#rand

Ayn Rand

Part 3 of 256.

/**
 * Randomly select an element from the array. The array remains unmodified.
 *
 * @returns A random element from an array, or undefined if the array is empty.
 */
Array.prototype.rand = function() {
  return this[rand(this.length)];
};

Building on the last installment of a global rand method, we can easily extend Array to provide simple random element selection.

// Example:
["rock", "paper", "scissors"].rand()

Selecting options from a loot table, or random AI actions is now wonderfully easy. With all these extensions the theme is the same, start with the best interface for the programmer and extend what you must to make it happen.

Useful JavaScript Game Extensions: rand

Rand Atlas Shrugged
Part 2 of my 256 part series: Useful JavaScript Game Extensions!

/**
 * Generate uniformly distributed random numbers.
 *
 * @param {Number} [n]
 * @returns A Random integers from [0, n) if n is given, otherwise a random float
 * between 0 and 1.
 * @type Number
 */
function rand(n) {
  if(n !== undefined) {
    return Math.floor(Math.random() * n);
  } else {
    return Math.random();
  }
}

Some games make use of random numbers… a lot. So when choosing the best interface it is important to keep that in mind. Often times uniform distributions are the way to go, such as when selecting from an array, or rolling a six sided die. If one often has need of a variety of random distributions then having different methods live in a Random namespace would probably be best. For simple, everyday use a little rand(6) is very convenient.