首先定义一个节点类
----定义节点类
local node= class("node")
--创建节点,x,y是map的item
ate(x,y,map)
local myNode={}
-- 节点在tmx的位置
myNode.x = x;
myNode.y = y;
---A start参数
myNode.g = 0; --当前节点到起始点的代价
myNode.h = 0; --当前点的终点的估价
myNode.f = 0; --f=g+h
myNode.father={} -- 记录父节点,用来回溯路径
return myNode
end
return node
有了node类,我们就可方便书写A start 算法主要逻辑
----A start寻路算法
local A_start= class("A_start")
local node = require("src/model/node")
local cost_stargiht =1 ; --直线移动花费
local cost_diag=1.414; --对角线移动花费
local MapY = 59 --地图y坐标最大值
local MapX = 89 --地图x坐标最大值
local _open = {}; --察表
local _close = {}; --以考察表
--计算某点的估值函数,可以多种实现
local function calculateH(point,endPoint)
print(endPoint.x , point.x)
----计算两个点的距离
local x = math.floor(endPoint.x - point.x) --获取该点x到终点x的距离
local y = math.floor(endPoint.y - point.y) --获取该点y到终点y的距离
local dis =math.abs(x)+math.abs(y)
--local dis = math.sqrt(math.pow(x,2)+math.pow(y,2))
return dis
end
---判断某点是否在close表内
local function isClose(point)
for key, var in ipairs(_close) do
if(var.x == point.x and var.y == point.y )then
return true
end
lua字符串转数组end
return false
end
---判断某点是否在open表内
local function isOpen(point)
for key, var in ipairs(_open) do
if(var.x == point.x and var.y == point.y )then
return true
end
end
return false
end
---寻路住逻辑,startPoint起始点,endPoint为终点,map为地图
function A_start.findPath(startPoint, endPoint, map)
_open = {}; --初始化
_close = {}; --初始化
--起始点
local point = ate(startPoint.x,startPoint.y,map)
point.g = 0
point.h = calculateH(point,endPoint)
point.f = point.g + point.h
--当前节点不等于终点
while(not(point.x == endPoint.x and point.y == endPoint.y))do
----获取其上下左右四点
local around={}
if(point.y > 0)then --上
table.insert(ate(point.x,point.y-1,map))
end
if(point.y < MapY)then --下
table.insert(ate(point.x,point.y+1,map))
end
if(point.x > 0)then --左
table.insert(ate(point.x-1,point.y,map))
end
if(point.x < MapX)then --右
table.insert(ate(point.x+1,point.y,map))
end
--检查周围点
for key, var in pairs(around) do
--如果不可行走或已在close表,忽略此点
if(isClose(var) or (veable))then
--print("忽略该点" .. var.x .. " " .. var.y)
else
--计算此点的代价
local g = cost_stargiht+ point.g -- G值等同于上一步的G值 + 从上一步到这里的成本
local h = calculateH(var,endPoint)
local f = g + h
--该点不在open列表内
if(not isOpen(var))then
var.g = g;
var.h = h;
var.f = f
var.father = point --指向父节点
table.insert(_open,var) -- 添加到open表
--如果在open表,进行f比较
else
for key1, var1 in ipairs(_open) do
if(var1.x == var.x and var1.y == var.y)then
--if(var1.f>f)then---两个版本,// 检查G值还是F值
if(var1.g>g)then
var1.f = f
var1.g = g
var1.h = h
var1.parent = point
end
break
end
end
end
end
end
----当前节点完一遍添加到——close表
table.insert(_close,point)
--open为空,则查失败
(_open)== 0)then
return 0 ---查失败返回0
end
-
--从open表去除最小的f点,并从open表移除
local max=99999
local myKey
for key2, var2 in ipairs(_open) do
if(var2.f<max)then
max = var2.f
myKey = key2
end
end
--从_open表移除并取出最小f的点最为起始点
point = ve(_open,myKey)
end
return point.father; -- 返回路径
end
return A_start
这样就完成了A start算法,下面我们来进行测试一下
--精灵移动方法,cocos2d 方法
local function Noderun(var,node)
veNum< (node.path))then
node.layer:getChildByTag(100):runAction(cc.Sequence:create(
cc.MoveTo:create(Soldier.speed,node.veNum]),cc.CallFunc:create(Noderun,node)))
else
end
end
local startItem = { x = 5,y = 57}
--终点
local endItem = { x = 20,y = 49}
--A_start寻路,调用寻路方法
local result = require("src/util/A_start").findPath(startItem,endItem,map)
---路径查到
if(result ~= 0)then
var.path = {} --path{}先清零
table.insert(var.path,Point(map,endItem)) -- 插入终点
--位置数组
--这里重要,是查到的路径,还记的在node定义的father变量吗,路径就得靠它,每一个结点的
--father属性都指向下一个结点,所以可以回溯出路径
while(result.x)do
local item = {x =result.x, y=result.y} --把所有item连起来解释路径
--Point()是转换为cocos2d的坐标,用于精灵移动
table.insert(var.path , 1 , Point(map,item))
result=result.father
end
-
-节点移动,这里是cocos2d-x 的结点移动,不会的不影响
Noderun("",var)
--路径 没到
else
print("查失败")
end
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论