//code by 月光 2005.9.22
//地图长宽
var mapx = 40;
var mapy = 40;
var total = mapx * mapy;
//边界距离
var distancex = 30;
var distancey = 30;
//移动速度
var interval = 75;
//初始障碍物比率
var balk = 3;
var val;
var width = 0;
var height = 0;
//移动次数
var moves = 0;
//是否正在忙碌
var busy = false;
//是否正在移动
var moving = false;
//是否搜索成功
var finded = false;
//路径记录
var open = new Array();
//方向数组 => 右, 下, 左, 上
var ori = new Array([1, 0], [0, 1], [-1, 0], [0, -1]);
// ========================================
//重置
var reset = function () {
clearInterval(val);
for (var i in _root) {
if (typeof _root[i] == "movieclip") {
_root[i].removeMovieClip();
}
}
txt.text = "";
init();
};
btn_reset.onPress = reset;
// ========================================
//初始化
var init = function () {
var i = 1;
// 绘制地图
while (i <= total) {
var tmp = attachMovie("mc", "m" + i, i, {id:i, visited:false});
tmp._x = (i - 1) % mapx * tmp._width + distancex;
tmp._y = Math.floor((i - 1) / mapy) * tmp._height + distancey;
if (random(balk) == 0) {
tmp.gotoAndStop(2);
}
i++;
}
m1.gotoAndStop(1);
width = m1._width;
height = m1._height;
// 主角初始位置
attachMovie("player", "player", total + 10000, {_x:distancex, _y:distancey});
player.onPress = function() {
busy = true;
txt.text = "请选择目标";
};
moving = false;
};
// ========================================
//点击地图后执行
btn.onPress = function() {
if (!moving) {
var i = 1;
while (i <= total) {
this._parent["m" + i].visited = false;
i++;
}
var x = Math.ceil((_xmouse - distancex) / width);
var y = Math.ceil((_ymouse - distancey) / height);
var id = x + (y - 1) * mapy;
//当前点击的MC
var tmp = this._parent["m" + id];
if (!busy) {
if (tmp._currentframe == 1) {
txt.text = "目标转换为障碍物";
tmp.gotoAndStop(2);
} else {
txt.text = "目标转换为通道";
tmp.gotoAndStop(1);
}
} else {
if (tmp._currentframe == 2) {
txt.text = "目标为障碍物,无法到达";
busy = false;
} else {
findit(x, y);
}
}
}
};
// ========================================
//寻路
var findit = function (x, y) {
finded = false;
open = new Array();
var playerx = Math.ceil((player._x - distancex) / width) + 1;
var playery = Math.ceil((player._y - distancey) / height) + 1;
moves = 1;
// 数组内元素为: X坐标, Y坐标, 距离原点长度, 上级位置
open[1] = [x, y, moves, 1];
for (i = 0; i < 4; i++) {
// 邻格内移动
if (x + ori[i][0] == playerx && y + ori[i][1] == playery) {
movefunc();
return;
}
}
// 非邻格内移动
var z = 1;
var t = 1;
while (open[z] != null) {
for (i = 0; i < 4; i++) {
var tmpx = open[z][0] + ori[i][0];
var tmpy = open[z][1] + ori[i][1];
if (tmpx > 0 && tmpy > 0 && tmpx <= 40 && tmpy <= 40) {
var id = tmpx + (tmpy - 1) * mapy;
var tmp = this["m" + id];
// 当对象存在及非障碍物及未访问过时
if (tmp != null && tmp._currentframe == 1 && !tmp.visited) {
tmp.visited = true;
open[++t] = [tmpx, tmpy, open[z][2] + 1, z];
if (open[t][0] == playerx && open[t][1] == playery) {
finded = true;
moves = z;
break;
}
}
}
}
z++;
}
if (finded) {
movefunc();
} else {
busy = false;
moving = false;
//debug
trace(open.join(" => "));
txt.text = "无法到达目标";
}
};
// ========================================
//角色移动
var movefunc = function () {
moving = true;
txt.text = "找到目标,正在移动";
val = setInterval(moveFunc, interval);
};
var moveFunc = function () {
updateAfterEvent();
moves = open[moves][3];
player._x = (open[moves][0] - 1) * width + distancex;
player._y = (open[moves][1] - 1) * height + distancey;
if (moves == 1) {
busy = moving = finded = false;
txt.text = "已到达目标";
clearInterval(val);
}
};
// ========================================
init();
stop();
本帖参考自OReilly的AI for Game Developers这本书的第七章A* Pathfinding,推荐对游戏开发有兴趣的朋友们可以找来研究下.
关于A*算法,也叫A STAR,这里有篇国人翻译的文章:
http://blog.vckbase.com/panic/archive/2005/03/20/3778.html
英文原文地址:
http://www.gamedev.net/reference/articles/article2003.asp