Javascript A*寻路(Craftyjs engine)

index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<script type="text/javascript" src="../crafty-0.6.1.js"></script>
	<script type="text/javascript" src="game.js"></script>
	<script type="text/javascript" src="scene.js"></script>
	
	<script>
		window.οnlοad=function(){
			Game.start();
			//console.log("make map "+i+","+j);
		}
	</script>
	<title>AStar</title>
</head>
<body>
</body>
</html>

scene.js

Crafty.scene('Main', function(){
	//
	console.log("main scene is load...");
	var walls = new Array();
	var wallNodes = new Array();
	var pathCubes = new Array();
	for(var i = 0; i < Game.tileX; i++){
		for(var j = 0; j < Game.tileY; j++){
			if(Crafty.math.randomNumber(1, Game.tileX-1)<9 && i>0 && i<Game.tileX-1 && j>0 && j<Game.tileY-1){
				//floor
				var wall = Crafty.e("2D, Canvas, Color, Solid").color("#A52A2A").attr({
					w: Game.tileWidth, h: Game.tileHeight,
					x: Game.tileWidth*i, y: Game.tileHeight*j
				});
				walls.push(wall);
				wallNodes.push(new Node(i, j));
			}else{
				//floor
				Crafty.e("2D, Canvas, Color, Mouse").color("#778899").attr({
					w: Game.tileWidth, h: Game.tileHeight,
					x: Game.tileWidth*i, y: Game.tileHeight*j
				}).bind('Click', function(e){
					
					//alert(Math.floor(e.clientX/Game.tileWidth)+","+Math.floor(e.clientY/Game.tileHeight));
					pathCubes.length = 0;
					/*
					for(el in pathCubes){
						el.destroy();
					}
					*/
					var path = Game.findPath(new Node(player.x, player.y), new Node(e.clientX, e.clientY), wallNodes);
					//console.log(path);
					
					for(var k=0; k<path.length; k++){
						var pathCube = Crafty.e("2D, Canvas, Color").color("#00FF00").attr({
							w: Game.tileWidth, h: Game.tileHeight,
							x: Game.tileWidth*path[k].x, y: Game.tileHeight*path[k].y
						}).timeout(function(){
								this.destroy();
						}, 3000);
						pathCubes.push(pathCube);
					}
					var dest = path.shift();
					player.x = dest.x * Game.tileWidth;
					player.y = dest.y * Game.tileHeight;
					
					
				});
			}
		}
	}
		
	//
	var player;
	var flag = true;
	while(flag){
		var playerX = Crafty.math.randomInt(1,Game.tileX-1);
		var playerY = Crafty.math.randomInt(1,Game.tileY-1);
		console.log("playerX:"+playerX+",playerY:"+playerY);
		for(var i=0; i<walls.length; i++){
			if(walls[i].x != playerX && walls[i].y != playerY){
				player = Crafty.e("2D, Canvas, Color").color("orange").attr({
					w: Game.tileWidth, h: Game.tileHeight,
					x: playerX*Game.tileWidth, y: playerY*Game.tileHeight, z: 99
				});
				flag = false;
				break;
			}
		}
	}
});

game.js

Game={
	tileWidth: 16,
	tileHeight: 16,
	width: 1280,
	height: 480,
	tileX: 80,
	tileY: 30,
	start: function(){
		Crafty.init(Game.width, Game.height);
		Crafty.background('rgb(87, 109, 20)');
		
		Crafty.scene('Main');
		
	},
	findPath: function(start, dest, walls){
		if(start.x == undefined || start.y == undefined || dest.x == undefined || dest.y == undefined){
			return undefined;
		}
		start.x = Math.floor(start.x/Game.tileWidth);
		start.y = Math.floor(start.y/Game.tileHeight);
		dest.x = Math.floor(dest.x/Game.tileWidth);
		dest.y = Math.floor(dest.y/Game.tileHeight);
		
		console.log("start:"+start.x+","+start.y+"/dest:"+dest.x+","+dest.y);
		var openList = new Array();
		var closeList = new Array();
		
		
		start.costFromStart = 0;
		start.costToObject = start.getCost(dest);
		
		openList.push(start);
		
		while(openList.length > 0){
			var firstNode = openList.shift(); //返回并删除第一个元素
			if(firstNode.x == dest.x && firstNode.y == dest.y){
				return Game.makePath(firstNode);
			}else{
				closeList.push(firstNode);
				var neighbors = firstNode.getNeighborNodes();
				for(var i=0; i<neighbors.length; i++){
					var neighborNode = neighbors[i];
					//是否在打开列表
					var isOpended = neighborNode.isPosCollided(openList);
					//是否在关闭列表
					var isClosed = neighborNode.isPosCollided(closeList);
					//是否和障碍碰撞
					var isCollideWithWall = neighborNode.isPosCollided(walls);
					
					if(!isOpended && !isClosed && !isCollideWithWall){
						neighborNode.costFromStart = firstNode.costFromStart + 1;
						neighborNode.costToObject = neighborNode.getCost(dest);
						neighborNode.parentNode = firstNode;
						
						//
						openList.push(neighborNode);
						Crafty.e("2D, Canvas, Color, Solid").color("lightblue").attr({
							w: Game.tileWidth, h: Game.tileHeight,
							x: Game.tileWidth*neighborNode.x, y: Game.tileHeight*neighborNode.y
						}).timeout(function(){this.destroy();}, 1500);
						//按近-远排序
						openList.sort(function(node1, node2){
							return (node1.costFromStart + node1.costToObject) - (node2.costFromStart + node2.costToObject);
						});
					}
				}
			}
		}
		openList = undefined;
		closeList = undefined;
		return undefined;
	},
	makePath: function(node){
		var path = new Array();
		while(node.parentNode != undefined){
			path.push(node);
			node = node.parentNode;
		}
		//add last node
		path.push(node);
		return path;
	},
	
};

function Node(posX, posY){
	this.x = posX;
	this.y = posY;
	this.costFromStart = undefined;
	this.costToObject = undefined;
	this.parentNode = undefined;
};

Node.prototype = {
	constructor: Node,
	getCost: function(node){
		if(node == undefined){
			return undefined;
		}
		return Crafty.math.distance(node.x, node.y, this.x , this.y);
	},
	getNeighborNodes: function(){
		var neighbors = new Array();
		neighbors.push(new Node(this.x + 1, this.y));
		neighbors.push(new Node(this.x, this.y + 1));
		neighbors.push(new Node(this.x - 1, this.y));
		neighbors.push(new Node(this.x, this.y - 1));
		return neighbors;
	},
	isPosCollided: function(arr){
		for(var i=0; i<arr.length; i++){
			if(arr[i] != undefined && arr[i].x == this.x && arr[i].y == this.y){
				return true;
			}
		}
		return false;
	}
};

顺便吐槽一下firefox32.0.3,改用360浏览器7.1挺好


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值