4 creative ways to clone objects

There are a lot of ways to clone objects in Javascript, and some of them get pretty creative. jQuery has an excellent method for cloning objects, as does Mootools. There’s a Javascript hack we can sort of “exploit”, or we could just clone our object in plain Javascript. Let’s start with the vanilla Javascript first and move on from there.

1) A vanilla Javascript method for cloning objects

This is a somewhat simple function that will clone an object and return the clone. If a non-object value is passed in, that value is returned.

// recursive function to clone an object. If a non object parameter
// is passed in, that parameter is returned and no recursion occurs.

function cloneObject(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}

var temp = obj.constructor(); // give temp the original obj's constructor
for (var key in obj) {
temp[key] = cloneObject(obj[key]);
}

return temp;
}

var bob = {
name: "Bob",
age: 32
};

var bill = (cloneObject(bob));
bill.name = "Bill";

console.log(bob);
console.log(bill);

If you try the above function, you’ll see that once bob has been cloned as bill, modifying values on bill won’t change the original values on bob.

2) A clever exploit of the JSON library to deep-clone objects

We can exploit the JSON library for a rather fast way of deep-cloning objects. Check it out:

var bob = {
name: "Bob",
age: 32
};

var bill = (JSON.parse(JSON.stringify(bob)));
bill.name = "Bill";

console.log(bob);
console.log(bill);

This method is nice and fast (faster as a rule than the jQuery method and possibly the Mootools function as well), and certainly rather less code than the first example. Plus, it’s pretty clever–just make sure you add a comment explaining what you’re doing. Otherwise, it could cause quite a bit of confusion!

3) Using jQuery’s $.extend() function

jQuery has a method that can be used to deep-clone objects, the $.extend() function. Let’s take a look at how it can be used:

var bob = {
name: "Bob",
age: 32
};

var bill = $.extend(true, {}, bob);
bill.name = "Bill";

console.log(bob);
console.log(bill);

Pretty handy, eh? This method is a little slower than the JSON exploit, but that shouldn’t really be a problem when you’re only doing a few clones. If you’re doing hundreds or thousands of clones, it might be time to think about the JSON exploit or another solution.

4) Using Mootools’ clone() function to clone objects

Last but not least, the Javascript library Mootools also provides a means of cloning objects–the rather aptly named clone() function. Observe the wild clone() in its natural habitat:

var bob = {
name: "Bob",
age: 32
};

var bill = Object.clone(bob);
bill.name = "Bill";

console.log(bob);
console.log(bill);

Implementation of A* Pathfinding in Javascript

I’ve been meaning to release my self-contained implementation of A* pathfinding for a while now, but it took me forever to get around to cleaning up the codebase and stuff. Anyways, once I did tidy it up, I decided to release it. Hopefully somebody out there will find it useful.

Here’s a demo of it in action:

Click anywhere to start a path, then click again to complete it. As you can see, my implementation is pretty quick. Although I haven’t measured its performance, strictly speaking, it can calculate a 850 or so unit long path with a barely visible delay (and I suspect even that delay is largely due to ‘s rendering performance–it really drops after you hit about nine million pixels, or 360,000 tiles). The algorithm uses a custom ordered array so it is pretty speedy.

Why use AStar.js?

If you’re interested in A* pathfinding, there are a few other pathfinding packages for Javascript. However, most of them require several Javascript libraries and/or complex inter-dependencies. To use my module, you only need to include one file–astar.js, and there are no external dependancies.

Getting started with AStar.js

Once you’ve included astar.js, you need to create an instance of the AStar pathfinding tool before you can start calculating your path. To create an instance of AStar, you need to provide your map data, the map’s height, the map’s width, and a function to tell whether or not a particular node is blocked.

Say your map data looks like this:

var map = [ 
[0, 1, 0, 0, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 1, 0, 0, 0],
];

You’d initialize your AStar object like this:

astar = new AStar(map, 7, 7, function(data, x, y) { 
return {
blocks: data[x][y]
}
});

The anonymous function you pass in takes three parameters; an inside reference to the data you passed in previously, the node’s x coordinate, and the node’s y coordinate. All it needs to return is an object with a boolean property, blocks, indicating whether or not the node in question is walkable. I may end up extending it to take values that let you determine the terrain cost of each node, but for now either a node is blocks movement or it doesn’t. In the case of the example, a “0” indicates unwalkable terrain and a “1” indicates walkable terrain. That’s why, in this example,  just returning the value at the specified node works.

Once you’ve initialized the AStar module, all it takes is a single line of code to get a path:

var path = astar.path(start_x, start_y, end_x, end_y);

AStar.path() returns an array containing the nodes found for the path specified, containing the starting and ending points. Each node is represented as an object with x and y values.

Demos and downloading AStar.js

You can find the link to the demo in the article here. I also put up a pathfinding stress test for fun; turns out that calculating an ~850 node long path takes about 200 ms (be warned, the linked page may take a while to load).

You can download AStar.js in an uncompressed format here (there’s also a minified version available). I hope somebody finds this helpful, and as always, be sure to let me know if I made any typos or errors in this article! (don’t forget to subscribe to my RSS feed, too)

Shadowcasting Field of View on Canvas with Javascript

A little while back, somebody asked me if I could turn the shadowcasting algorithm I posted here into a working demo. After a bit of fiddling around I set up a demo using the tag for display (and in the process made a little shadowcasting library-ling [what do you call a miniature library, exactly?] called LightSource). There are two versions, a fullscreen demo and the little one you see embedded below. The fullscreen demo has a bunch of controls that let you control the light output in various ways, and you can click+drag to create walls (click them again to remove them). It’s really a lot of fun to fiddle around with–although it does get a bit slow when you have lights with a radius of over 90 tiles–and you can reach it by clicking here. Happy shadowcasting!

But how do pretty light?

“That’s all very nice,” you say, “but how can I make this happen?” Well, the basic code behind the demo is simple. First, you need create an instance of the LightSource object with a few parameters. There are three parameters that are required initially–the radius of the light source (can be changed later), the size of the map you want to light and a function that will determine whether a particular tile blocks light. Altogether, your initialization script should look like this:

var light = new LightSource({ 
radius: 6,
mapSize: this.mapSize,
getLightLevel: function(x, y) {
return map[x][y].blocksLight; // whether or not the tile at x, y in your map blocks light
}
});

Once you’ve successfully initialized your light source you’ll then need to call light.update(x, y) with the position of your light source. This function will return an array of objects representing all tiles that are affected by the light source as well as their respective light levels in this format:

tile { 
x: // x coordinate
y: // y coordinate lightLevel: // the level of light on this tile
}

The lightLevel of each tile is a value between 0 and 1 and is determined by its distance from the light source (unless specified otherwise by including gradient: false in the initialization parameters). This means that the light fades away nicely from full strength at the center of the light to almost nothing at the borders of the light, until finally we reach 0.

But anyways, I digress. Once you’ve got this list, you can then iterate through it and apply the changes to your actual map data. After that’s done, you’ll want to render your changes. I used to do this, but you’re not limited to that. In fact, the LightSource library is untethered to display as it only handles behind-the-scenes data, thanks to the callback method I implemented. So go ahead and feel free to use whatever display method you want.

Download LightSource

Before you leave, here’s a link to download LightSource.js–hopefully you find it useful. If you do make anything cool with it, please don’t forget to comment and show me what you’ve come up with!

I hope you find LightSource useful, and as always, feel free to comment and tell me if I’ve missed anything or made any mistakes in this post or in the LightSource algorithm.