首页 > 代码库 > HTML5-寻路跟踪

HTML5-寻路跟踪

<script type="text/javascript"> var map = new Array(); var mapWidth = 100; var mapHeight = 100; var mapDrawX = 0; var mapDrawY = 0; var speed = 1; var blockWidth = 15; var blockHeight = 15; var isKeyLeft = false; var isKeyRight = false; var isKeyUp = false; var isKeyDown = false; var me_x = startX = 0; var me_y = startY = 0; var enem_x = 30; var enem_y = 30; var pathFinder; var pathPoints; // 路径点定义 function Point(x, y) { this.x = x; this.y = y; this.parentPoint; this.f = 0; this.g = 0; this.h = 0; } // 寻路类定义 function PathFinder(map) { this.map = map; this.OBLIQUE = 14; this.STEP = 10; this.openList = new Array(); this.closeList = new Array(); // 计算G值 this.calc_g = function (start, point) { var g = (Math.abs(point.x - start.x) + Math.abs(point.y - start.y)) == 2 ? this.STEP : this.OBLIQUE; var parent_g = point.parentPoint != null ? point.parentPoint.g : 0; return g + parent_g; } // 计算H值 this.calc_h = function (end, point) { var step = Math.abs(point.x - end.x) + Math.abs(point.y - end.y); return step * this.STEP; } // 判断路径点是否在集合当中 this.isPointExistInArray = function (x, y, points) { for (var i = 0; i < points.length; i++) { if (points[i].x == x && points[i].y == y) { return true; } } return false; } // 获取集合中指定的路径点 this.getPointInArray = function (point, points) { for (var i = 0; i < points.length; i++) { if (points[i].x == point.x && points[i].y == point.y) { return points[i]; } } return null; } // 获取集合中F值最小的路径点 this.getMinPoint = function (points) { var min = points[0]; var idx = 0; for (var i = 1; i < points.length; i++) { if (points[i].f < min.f) { min = points[i]; idx = i; } } return { point: min, index: idx }; } // 判断路径点是否可以到达 this.canReach = function (x, y) { if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight) { return false; } if (map[x * mapWidth + y] != 0) { return false; } return true; } // 判断路径点是否可以到达 this.canReachTo = function (start, x, y, isIgnoreCorner) { if (!this.canReach(x, y) || this.isPointExistInArray(x, y, this.closeList)) return false; if (Math.abs(x - start.x) + Math.abs(y - start.y) == 1) return true; if (this.canReach(x - (x - start.x), y) && this.canReach(x, y - (y - start.y))) return true; return isIgnoreCorner; } // 获取路径点周围所有可以到达的路径点 this.getSurroundPoints = function (point, isIgnoreCorner) { var surroundPoints = new Array(); for (var x = point.x - 1; x <= point.x + 1; x++) { for (var y = point.y - 1; y <= point.y + 1; y++) { if (this.canReachTo(point, x, y, isIgnoreCorner)) { var tempPoint = new Point(x, y); surroundPoints.push(tempPoint); } } } return surroundPoints; } // 如果未找到路径点,执行此函数 this.joinOpenList = function (tempStart, end, point) { point.parentPoint = tempStart; point.g = this.calc_g(tempStart, point); point.h = this.calc_h(end, point); point.f = point.g + point.h; this.openList.push(point); } // 寻路方法 this.findPath = function (start, end, isIgnoreCorner) { this.openList.push(start); while (this.openList.length > 0) { // 找出F值最小的点 var temp = this.getMinPoint(this.openList); var tempStart = temp.point; this.openList.splice(temp.index, 1); this.closeList.push(tempStart); // 找出它相邻的点 var surroundPoints = this.getSurroundPoints(tempStart, isIgnoreCorner); for (var i = 0; i < surroundPoints.length; i++) { if (!this.isPointExistInArray(surroundPoints[i].x, surroundPoints[i].y, this.openList)) { // 如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF this.joinOpenList(tempStart, end, surroundPoints[i]); } } // 如果终点出现在开始列表,则表示寻路结束 var point = this.getPointInArray(end, this.openList); if (point != null) { var pathPoints = new Array(); var parentPoint = point; while (parentPoint != null) { pathPoints.push(parentPoint); parentPoint = parentPoint.parentPoint; } pathPoints.splice(pathPoints.length - 1, 1); return pathPoints; } } return null; } } function getRandom(min, max) { return Math.round(Math.random() * (max - min) + min); } var traceDelay = 3; var traceDelayCounter = 0; var canvas; var contex; function refreshFunc() { context.clearRect(0, 0, canvas.width, canvas.height); var old_x = me_x; var old_y = me_y; if (isKeyLeft) { me_x -= speed; } if (isKeyRight) { me_x += speed; } if (isKeyUp) { me_y -= speed; } if (isKeyDown) { me_y += speed; } if (me_x < 0 || me_x > mapWidth || me_y < 0 || me_y >= mapHeight|| map[me_x * mapWidth + me_y] != 0) { if (isKeyLeft) { me_x += speed; } if (isKeyRight) { me_x -= speed; } if (isKeyUp) { me_y += speed; } if (isKeyDown) { me_y -= speed; } } if (me_x != old_x || me_y != old_y) { var start = new Point(enem_x, enem_y); var end = new Point(me_x, me_y); pathFinder = new PathFinder(map); pathPoints = pathFinder.findPath(start, end, false); } if (pathPoints != null && pathPoints.length > 0) { traceDelayCounter++; if (traceDelayCounter == traceDelay) { enem_x = pathPoints[pathPoints.length - 1].x; enem_y = pathPoints[pathPoints.length - 1].y; pathPoints.splice(pathPoints.length - 1, 1); traceDelayCounter = 0; } } for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { if (map[x * mapWidth + y] == 0) { context.fillStyle = "#eeeeee"; } else { context.fillStyle = "#cccccc"; } context.fillRect((mapDrawX + startX - me_x + x) * blockWidth, (mapDrawY + startY - me_y + y) * blockHeight, blockWidth, blockHeight); context.strokeStyle = "#dddddd"; context.strokeRect((mapDrawX + startX - me_x + x) * blockWidth, (mapDrawY + startY - me_y + y) * blockHeight, blockWidth, blockHeight); } } context.fillStyle = "Red"; context.fillRect((mapDrawX + startX) * blockWidth, (mapDrawY + startY) * blockHeight, blockWidth, blockHeight); context.fillStyle = "Blue"; context.fillRect((mapDrawX + startX - me_x + enem_x) * blockWidth, (mapDrawY + startY - me_y + enem_y) * blockHeight, blockWidth, blockHeight); } function init() { canvas = document.getElementById("view"); context = canvas.getContext("2d"); me_x = mapWidth / 2; me_y = mapHeight / 2; startX = mapWidth / 2; startY = mapHeight / 2; mapDrawX = (canvas.width - mapWidth * blockWidth) / 2 / blockWidth; mapDrawY = (canvas.height - mapHeight * blockHeight) / 2 / blockHeight; for (var x = 0; x < mapWidth; x++) { for (var y = 0; y < mapHeight; y++) { map[x * mapWidth + y] = getRandom(0, 5) == 0 ? 1 : 0; } } setInterval(refreshFunc, 30); } init(); document.onkeydown = function (e) { e = e || window.event; switch (e.which) { case 37: isKeyLeft = true; break; case 39: isKeyRight = true; break; case 38: isKeyUp = true; break; case 40: isKeyDown = true; break; } } document.onkeyup = function (e) { e = e || window.event; switch (e.which) { case 37: isKeyLeft = false; break; case 39: isKeyRight = false; break; case 38: isKeyUp = false; break; case 40: isKeyDown = false; break; } } </script>