<body>
    <div id="container"></div>

    <script src="https://rawgit.com/mrdoob/three.js/dev/build/three.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/Detector.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/libs/stats.min.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
    <script src = "https://dl.dropboxusercontent.com/s/zjt32xn2mlyflvy/easystar-0.3.1.min.js"</script>
<link href='https://fonts.googleapis.com/css?family=Barrio' rel='stylesheet'>
<link href='https://fonts.googleapis.com/css?family=Butcherman' rel='stylesheet'>

<div id="loader"></div>
</body>
var astar = {
		init: function (graph) {
			for (var x = 0; x < graph.length; x++) {
				//for(var x in graph) {
				var node = graph[x];
				node.f = 0;
				node.g = 0;
				node.h = 0;
				node.cost = 1.0;
				node.visited = false;
				node.closed = false;
				node.parent = null;
			}
		},
		cleanUp: function (graph) {
			for (var x = 0; x < graph.length; x++) {
				var node = graph[x];
				delete node.f;
				delete node.g;
				delete node.h;
				delete node.cost;
				delete node.visited;
				delete node.closed;
				delete node.parent;
			}
		},
		heap: function () {
			return new BinaryHeap(function (node) {
				return node.f;
			});
		},
		search: function (graph, start, end) {
			astar.init(graph);
			//heuristic = heuristic || astar.manhattan;


			var openHeap = astar.heap();

			openHeap.push(start);

			while (openHeap.size() > 0) {

				// Grab the lowest f(x) to process next.  Heap keeps this sorted for us.
				var currentNode = openHeap.pop();

				// End case -- result has been found, return the traced path.
				if (currentNode === end) {
					var curr = currentNode;
					var ret = [];
					while (curr.parent) {
						ret.push(curr);
						curr = curr.parent;
					}
					this.cleanUp(ret);
					return ret.reverse();
				}

				// Normal case -- move currentNode from open to closed, process each of its neighbours.
				currentNode.closed = true;

				// Find all neighbours for the current node. Optionally find diagonal neighbours as well (false by default).
				var neighbours = astar.neighbours(graph, currentNode);

				for (var i = 0, il = neighbours.length; i < il; i++) {
					var neighbour = neighbours[i];

					if (neighbour.closed) {
						// Not a valid node to process, skip to next neighbour.
						continue;
					}

					// The g score is the shortest distance from start to current node.
					// We need to check if the path we have arrived at this neighbour is the shortest one we have seen yet.
					var gScore = currentNode.g + neighbour.cost;
					var beenVisited = neighbour.visited;

					if (!beenVisited || gScore < neighbour.g) {

						// Found an optimal (so far) path to this node.  Take score for node to see how good it is.
						neighbour.visited = true;
						neighbour.parent = currentNode;
						if (!neighbour.centroid || !end.centroid) debugger;
						neighbour.h = neighbour.h || astar.heuristic(neighbour.centroid, end.centroid);
						neighbour.g = gScore;
						neighbour.f = neighbour.g + neighbour.h;

						if (!beenVisited) {
							// Pushing to heap will put it in proper place based on the 'f' value.
							openHeap.push(neighbour);
						} else {
							// Already seen the node, but since it has been rescored we need to reorder it in the heap
							openHeap.rescoreElement(neighbour);
						}
					}
				}
			}

			// No result was found - empty array signifies failure to find path.
			return [];
		},
		heuristic: function (pos1, pos2) {
			return distanceToSquared(pos1, pos2);
		},
		neighbours: function (graph, node) {
			var ret = [];

			for (var e = 0; e < node.neighbours.length; e++) {
				ret.push(graph[node.neighbours[e]]);
			}

			return ret;
		}
	};




var scene, renderer, camera;
var cube;
var controls;
var mega1, mega2;
var grid, finder;
var enemy, player, enemy2, player2;
var easystar;

// Map generation (visit rooms)

// Create a 2D array of booleans.
// True means we can walk on, false means it's a wall.
function createHuntsMaze(w, h, cx, cy)
{
	// With and height not set? stop
  if (!w || !h)
    return [];

	// Store all the visited areas
	var visited = [];

  // Build the array
  var map = [];

	// Creates the 2nd dimension of the array
  for (var i = 0; i < w; i++)
    map[i] = [];

	// Offset if the array doesn't fit our needs.
  var offX = 1 - (cx % 2);
  var offY = 1 - (cy % 2);

	// Init the map and the visited array
  for (var i = 0; i < w; i++)
  {
    for (var j = 0; j < h; j++)
    {
      map[i][j] = false;
      visited[i + j * w] = false;
    }
  }
  
  // Fill each 2nd cell with a true (those are the rooms)
  for (var i = 0; i < w - offX; i++)
  {
    for (var j = 0; j < h - offY; j++)
    {
      if (i % 2 == 1 && j % 2 == 1 && i < w - (1 + offX) && j < h - (1 + offY))
        map[i + offX][j + offY] = true;
      else
        map[i + offX][j + offY] = false;
    }
  }

	// Set the start point of the visit
  var todo = [{ x: 1 + offX, y: 1 + offY }];
  var done = [];

  visited[todo[0].x + todo[0].y * w] = true;
  var maxSteps = Math.round(w * h / 3);

	// While we have something to visit
  while (todo.length > 0 && maxSteps > 0)
  {
    maxSteps--;
    // Pick a random item from the todo
    var s = Math.floor(Math.random() * todo.length);
    var c = todo[s];
    done[done.length] = c;
    todo.splice(s, 1);

		// Check if we can go to a room left (2 cells left)
    if (c.x > 1 + offX && visited[(c.x - 2) + c.y * w] == false)
    {
      todo[todo.length] = { x: c.x - 2, y: c.y };
      visited[(c.x - 2) + c.y * w] = true;
      // Open the wall to left
      map[(c.x) - 1][c.y] = true;
    }
		// Check if we can go to a room up (2 cells up)
    if (c.y > 1 + offY && visited[(c.x) + (c.y - 2) * w] == false)
    {
      todo[todo.length] = { x: c.x, y: c.y - 2 };
      visited[(c.x) + (c.y - 2) * w] = true;
      // Open the wall to up
      map[c.x][(c.y) - 1] = true;
    }
		// Check if we can go to a room right (2 cells right)
    if (c.x + 2 < w - 1 && visited[(c.x + 2) + c.y * w] == false)
    {
      todo[todo.length] = { x: c.x + 2, y: c.y };
      visited[(c.x + 2) + c.y * w] = true;
      // Open the wall to right
      map[(c.x) + 1][c.y] = true;
    }
		// Check if we can go to  room right (2 cells down)
    if (c.y + 2 < h - 1 && visited[(c.x) + (c.y + 2) * w] == false)
    {
      todo[todo.length] = { x: c.x, y: c.y + 2 };
      visited[(c.x) + (c.y + 2) * w] = true;
      // Open the wall to bottom
      map[c.x][(c.y) + 1] = true;
    }
  }

  return map;
}

init();
animate();

function init()
{
	renderer = new THREE.WebGLRenderer( {antialias:true} );
	var width = window.innerWidth;
	var height = window.innerHeight;
	renderer.setSize (width, height);
	document.body.appendChild (renderer.domElement);

	scene = new THREE.Scene();
   //scene.fog = new THREE.FogExp2(0x1E2630, 0.002);
  renderer.setClearColor("yellow");
  	var cubeGeometry = new THREE.BoxGeometry (10,10,10);
	var cubeMaterial = new THREE.MeshLambertMaterial ({color: 0x1ec876});
	// Create a maze and render it
// Create a maze and render it

var maze = createHuntsMaze(20,20,65,65);
function buildMaze()
{
	
 
  for(var x=0;x < maze.length;x++)
  {
  	for(var y=0;y < maze.length;y++)
    {
	
    	if(maze[x][y] === true)
    		continue;
              // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
   cube = new THREE.Mesh (cubeGeometry, cubeMaterial);

	cube.position.set (50, 0, 0);
	scene.add (cube);

    // Move the sphere upward 1/2 its height
   cube.position.x = x*120;
     cube.position.z = y*120;
     cube.scale.z = 10;
     cube.scale.y = 10;
     cube.scale.x = 10;
     }
    
  }
}

buildMaze();

   var player = {
    x: 0,
    y: 0
};

var enemy = {
    x: 2,
   y: 2
};
 
mega1 = new THREE.Mesh (new THREE.BoxGeometry (80,80,80), new THREE.MeshLambertMaterial ({color: "blue"}));
mega1.position.set(player.x, 0, player.y)
	scene.add (mega1);
	player2 = {
    x: 0*mega1.position.x,
    y: 0*mega1.position.z
};
  mega2 = new THREE.Mesh (new THREE.BoxGeometry (40,40,40), new THREE.MeshLambertMaterial ({color: "red"}));
mega1.position.set(enemy.x, 0, enemy.y)
	scene.add (mega2);
enemy2 = {
x: 5*mega2.position.x,
y: 4*mega2.position.z
}
  
  var mze = [
    [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
    [ 1, 0, 1, 0, 0, 0, 0, 0, 1, 0],
    [ 0, 0, 0, 0, 1, 1, 1, 0, 1, 0],
    [ 0, 1, 1, 0, 0, 0, 1, 0, 1, 0],
    [ 0, 0, 1, 1, 1, 1, 1, 0, 1, 0],
    [ 1, 0, 1, 0, 0, 0, 1, 0, 1, 0],
    [ 1, 0, 1, 0, 1, 0, 1, 0, 0, 0],
    [ 1, 0, 1, 0, 1, 0, 0, 1, 1, 0],
    [-1, 0, 1, 0, 1, 1, 0, 0, 0, 0]
];
  //easystar
   var graph = new Graph(mze, { diagonal: false });
   var start = graph.grid[enemy.x][enemy.y];
	var end = graph.grid[player.x][player.y];
	//var result = astar.search(graph, [0, 0], [2, 2]);
 	var result = astar.search(graph, start, end);
  function pathToString(result) {
  return result.map(function(node) {
    return "(" + node.x + "," + node.y + ")";
  }).join("");
}
var current = result.shift();
 for(var i = 0; i<result.length; i++){
    console.log(result[i])
 }
   easystar = new EasyStar.js();
    easystar.setGrid(maze)
    easystar.setAcceptableTiles([false]);
   easystar.enableDiagonals();// we want path to have diagonals
    easystar.disableCornerCutting();// no diagonal path when walking at wall corners
    easystar.setIterationsPerCalculation(1000);

  
  grid = new PF.Grid(mze.length, mze.length, mze);
    finder = new PF.AStarFinder({allowDiagonal: true});
   var path = finder.findPath(0, 0, 3, 3, grid.clone());
 var current = path.shift();
   console.log(path)
   for(var i = 0; i<path.length; i){
    // console.log("x"+path[i][0]+" y"+path[i][1]);
    // console.log(dy);
 //  var tween = createjs.Tween.get(mega2.position, {loop: false})
         //.to({x: path[i][0], z: path[i][1]}, 70);
    }
 
   
	camera = new THREE.PerspectiveCamera (45, width/height, 1, 10000);
	camera.position.y = 160;
	camera.position.z = 400;
	camera.lookAt (new THREE.Vector3(0,0,0));

    controls = new THREE.OrbitControls (camera, renderer.domElement);
    
	var gridXZ = new THREE.GridHelper(100, 10);
	gridXZ.setColors( new THREE.Color(0xff0000), new THREE.Color(0xffffff) );
	scene.add(gridXZ);
function canMove(x, y){
    return (y>=0) && (y<world.length) && (x >= 0) && (x < world[y].length) && (world[y][x] != true);
}

document.addEventListener("keyup", function(e){
    if((e.which == 38) && canMove(mega1.position.x, mega1.position.z-1))//Up arrow
        mega1.position.z--;
    else if((e.which == 40) && canMove(mega1.position.x, mega1.position.z+1)) // down arrow
        mega1.position.z++;
    else if((e.which == 37) && canMove(mega1.position.x-1, mega1.position.z))
        mega1.position.x--;
    else if((e.which == 39) && canMove(mega1.position.x+1, mega1.position.z))
        mega1.position.x++;
        //find collision
      // var path = new astar();
  //path.init(mze)
        
console.log("this"+astar.search(maze,[0, 1], [2, 3]))
    
    e.preventDefault();
});
	var pointLight = new THREE.PointLight (0xffffff);
	pointLight.position.set (0,300,200);
	scene.add (pointLight);
	
	window.addEventListener ('resize', onWindowResize, false);
}

function onWindowResize ()
{
	camera.aspect = window.innerWidth / window.innerHeight;
	camera.updateProjectionMatrix();
	renderer.setSize (window.innerWidth, window.innerHeight);
}

function animate()
{
  
	controls.update();
    requestAnimationFrame ( animate );  
	renderer.render (scene, camera);
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdn.rawgit.com/schteppe/PathFinding3D.js/master/lib/pathfinding-browser.js
  2. https://code.createjs.com/tweenjs-0.6.0.min.js
  3. https://code.createjs.com/createjs-2014.12.12.min.js
  4. https://code.createjs.com/easeljs-0.8.0.min.js
  5. https://dl.dropboxusercontent.com/s/zjt32xn2mlyflvy/easystar-0.3.1.min.js
  6. https://cdn.rawgit.com/bgrins/javascript-astar/master/astar.js