因为游戏初步定为塔防类型,所以这里需要个简单的寻路算法,玩法对寻路效率要求并不高,所以就实现了个最简单的寻路算法
1.只能上下左右走
2.未做任何优化,可优化空间较大
3.初步测试, 15*15格子 什么都不摆 耗时 2 毫秒 (a*算法在没有障碍物的情况下基本上要遍历所有的路径,所以在这种情况下是最耗时的)
(蓝:start 绿:end 红:障碍 黄:路径)
代码如下,注释较多,有问题可以留言,代码文件可以直接拿到自己工程里使用
XXAStar = {}
local function removeChild(parent,child) --table 删除子
local list = parent
for k,v in pairs(list) do
if v == child then
table.remove(list,k)
return list
end
end
end
local function getRoundPos(pos,closeList,openList) --寻找周围合法点,不在open 也不在close
local px = pos.x
local py = pos.y
local list = {
{x=px ,y=py+1}, --上
{x=px-1 ,y=py}, --左
{x=px+1 ,y=py}, --右
{x=px ,y=py-1}, --下
}
local returnList = {}
for _,v in pairs(list) do
if v.x >= 1 and v.y >= 1 then --地图范围内
if v.x <= XXAStar.size.width and v.y <= XXAStar.size.height then
if closeList[v.x][v.y] == 0 then --排除closelist
local isInOpen = nil
for _,v1 in pairs(openList) do --排除open列表
if v1.x == v.x and v1.y == v.y then
isInOpen = v1
end
end
if isInOpen == nil then
table.insert( returnList,v )
else --如果在open中 需要更新查看F是否更小
local newG = pos.g + (math.abs(pos.x - v.x) + math.abs(pos.y - v.y) )
if newG < isInOpen.g then
isInOpen.parent = pos
isInOpen.g = newG
end
end
end
end
end
end
return returnList
end
local function countFGH(startpos,endpos,list) --计算 FGH
-- G = 从 起点 移动到 指定点
-- H = 从 指定点 移动到 终点
-- F = G + H
local minF = nil
for _,v in pairs(list) do
if v.g == nil then
v.g = math.abs(startpos.x - v.x) + math.abs(startpos.y - v.y)
v.h = math.abs(v.x - endpos.x) + math.abs(v.y - endpos.y)
v.f = v.g+v.h
end
if minF == nil then
minF = v
end
if v.f < minF.f then
minF = v
end
end
return minF
end
function XXAStar:init()
--寻路二维数组
self.size = {width=0,height=0} --尺寸
self.pathList = {} --路径数据
self.startPos = nil --起始点
self.endPos = nil --终止点
self.openList = {}
self.closeList = {}
end
function XXAStar:getPath(width,height,startpos,endpos,closeList)
--初始化
self:init()
self.size.width = width
self.size.height = height
for j=1,width,1 do
self.pathList[j] = {}
self.closeList[j] = {}
for i=1,height,1 do
self.pathList[j][i] = { type = 0 }
self.closeList[j][i] = 0
end
end
self.startPos = startpos
self.endPos = endpos
--1.起始点加入到open列表中
table.insert(self.openList,self.startPos)
--2.将障碍物放到close列表
for k,v in pairs(closeList) do
self.pathList[v.x][v.y].type = 1
self.closeList[v.x][v.y] = 1
end
--8.回溯路径
local resultList = {}
local lastPos = self:countPath(self.startPos)
if lastPos == nil then
return {}
end
while(true)
do
if lastPos.parent == nil then
break
end
if lastPos.parent.x == self.startPos.x and lastPos.parent.y == self.startPos.y then
break
end
table.insert( resultList,{x=lastPos.parent.x,y=lastPos.parent.y} )
lastPos = lastPos.parent
end
return resultList
end
function XXAStar:countPath( firstPos )
--3.根据起点寻找周围相邻点,排除障碍物
local roundlist = getRoundPos(firstPos,self.closeList,self.openList)
--4.把起点从openlist中移除,加入到closelist
self.openList = removeChild(self.openList,firstPos)
self.closeList[firstPos.x][firstPos.y] = firstPos
--5.找到的点加入到openlist
for _,v in pairs(roundlist) do
v.parent = firstPos
table.insert(self.openList,v)
--6 查看是否找到了终点
if v.x == self.endPos.x and v.y == self.endPos.y then
return v
end
end
--7.计算 FGH 并得到f最小的值
local minF = countFGH(self.startPos,self.endPos,self.openList)
if minF == nil then
--已经没有未遍历的点了
return nil
else
return self:countPath(minF)
end
end
使用示例:
--[[
function XXAStar:getPath(width,height,startpos,endpos,closeList)
--width,height 尺寸
--startpos 起始点
--endpos 终止点
--closeList 障碍物
]]--
local usePosList = XXAStar:getPath(15,15,{x=1,y=1},{x=15,y=15},closeList)
if table.getn(usePosList) == 0 then
XXLog("没有找到路径")
else
--TODO
--usePosList 路径的坐标点集合
end