-- 偏移量
local NearGridOffsets = {-1, 99, 100, 101, 1, -99, -100, -101}
-- 初始移动点
function MyGameScene:initPos()
local points = {
8,3,8,4,8,5,8,7,8,8,8,9,8,10,8,11,8,12,8,13,8,14,8,15,8,17,8,18,
8,19,8,20,8,21,8,22,8,23,8,24,8,25,8,26,8,27,
8,30,8,31,8,32,8,33,8,34,8,35,8,36,8,37,8,38,8,39,
9,4,9,7,9,12,9,13,9,14,9,15,9,16,9,17,9,18,9,19,9,20,9,21,9,22,9,23,9,24,9,25,
9,26,9,27,9,28,9,29,9,30,9,31,9,32,9,33,9,34,9,35,9,36,9,37,9,38,9,39,
10,4,10,5,10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,10,18,
10,19,10,20,10,21,10,22,10,23,10,24,10,25,10,26,10,27,10,28,10,29,
10,30,10,31,10,32,10,33,10,34,10,35,10,36,10,38,10,39,
11,5,11,6,11,7,11,8,11,9,11,10,11,11,11,12,11,13,11,14,11,15,11,16,11,17,11,18,
11,19,11,27,11,28,11,29,11,30,11,31,11,32,11,33,11,34,11,35,11,36,11,38,11,39,
12,5,12,8,12,9,12,10,12,12,12,13,12,14,12,15,12,16,12,17,12,28,12,29,
12,30,12,31,12,32,12,33,12,34,12,35,12,36,12,37,
13,5,13,6,13,7,13,8,13,9,13,10,13,11,13,12,13,13,13,14,13,15,13,16,13,17,
13,28,13,29,13,30,13,31,13,32,13,33,13,34,13,35,13,36,13,37,13,38,
14,9,14,8,14,10,14,11,14,12,14,13,14,14,14,15,14,16,14,17,
14,28,14,29,14,30,14,31,14,32,14,33,14,34,14,35,14,36,14,37,14,38,
15,12,15,13,15,14,15,15,15,16,15,17,
15,28,15,29,15,30,15,31,15,32,15,33,15,34,15,35,
16,9,16,10,16,11,16,12,16,13,16,14,16,15,16,16,16,17,16,18,
16,19,16,27,16,28,16,29,16,30,16,31,16,32,16,35,16,36,16,37,
17,9,17,10,17,12,17,13,17,14,17,15,17,16,17,17,17,18,17,19,
17,20,17,21,17,22,17,23,17,24,17,25,17,26,17,27,17,28,17,29,
17,30,17,31,17,35,17,36,17,37,
18,10,18,12,18,13,18,14,18,15,18,16,18,17,18,18,18,19,
18,20,18,21,18,22,18,23,18,24,18,25,18,26,18,27,18,28,18,29,18,35,18,36,
19,24,20,23,20,24,20,25,
}
-- 初始可以行走的点
self.grids = {}
local rc, r, c
for i=1,#points,2 do
r,c = points[i],points[i+1]
rc = r * 100 + c
self.grids[rc] = {
rc = rc,
r = r,
c = c,
}
end
end
-- 是否存在该点
function MyGameScene:isInvalidPoint(rc)
return self.grids[rc]
end
-- 查找指定的点是否在列表中
local function findPoint(ps, rc)
for _, p in ipairs(ps) do
if p.rc == rc then
return p
end
end
return nil
end
-- 计算两点之间的距离
local function distance(p1, p2)
local x1, y1 = 0, 0
if p1 >= 1000 then
x1, y1 = p1 % 100, math.floor(p1 / 100)
else
x1, y1 = p1 % 10, math.floor(p1 / 10)
if y1 == 2 or y1 == 4 then
x1 = x1 + 0.5
end
end
local x2, y2 = 0, 0
if p2 >= 1000 then
x2, y2 = p2 % 100, math.floor(p2 / 100)
else
x2, y2 = p2 % 10, math.floor(p2 / 10)
if y2 == 2 or y2 == 4 then
x2 = x2 + 0.5
end
end
return math.sqrt((x1-x2)^2 + (y1 - y2)^2)
end
-- 将点位按f值升序
local function sortPointAsc(ps)
table.sort(ps, function(p1, p2)
return p1.f < p2.f
end)
end
function MyGameScene:findPath(from,dest)
if from == dest then
return {}
end
local dp = nil -- 目标值
local rc = nil
local g = nil
local h = nil
local np = nil
local opens = {
{
rc = from,
g = 0, -- 当前节点到起始点的估计
h = nil, -- 当前点到终点的估计
f = 0,
from = nil, -- 该点的前一格点
wc = 0, -- 已移动的格子数
}
}-- 开放列表
local closes = {} -- 关闭列表
while #opens > 0 do
cp = opens[1]
-- 获取附近的点
for _, ofs in ipairs(NearGridOffsets) do
rc = cp.rc + ofs
-- 目标点
if rc == dest then
dp = {rc = dest, from = cp, wc = cp.wc+1}
break
end
-- 是否存在该点,并且不在关闭列表中
if self:isInvalidPoint(rc) and not findPoint(closes,rc) then
g = distance(cp.rc,rc) + cp.g -- 到该点所需要的消耗值
np = findPoint(opens,rc) -- 是否在开放列表中
if np then --如果存在
-- 比较f值
f = np.h + g
--[[
当新的cp点到 rc 该点所f消耗少,把新的cp则替换之前的form点
]]--
if f < np.f then
np.f = f
np.g = g
np.from = cp
end
else
-- 不存在放入开放列表中
h = distance(rc, dest)
opens[#opens + 1] = {
rc = rc,
g = g,
h = h,
f = g + h,
from = cp,
wc = cp.wc+1,
}
end
end
end
-- 找到了目标点
if dp then
break
end
-- 将该点从开放列表中移除
table.remove(opens, 1)
closes[#closes+1] = cp
sortPointAsc(opens)
end
if dp == nil then
return {}
end
-- 路径
local path = {}
repeat
path[#path + 1] = dp.rc
dp = dp.from
until dp == nil or dp.rc == from
-- 将数据反序
local endIndx = #path
for i = 1, endIndx do
if i >= endIndx then
break
end
path[endIndx], path[i] = path[i], path[endIndx]
endIndx = endIndx - 1
end
return path
end
local NearGridOffsets = {-1, 99, 100, 101, 1, -99, -100, -101}
-- 初始移动点
function MyGameScene:initPos()
local points = {
8,3,8,4,8,5,8,7,8,8,8,9,8,10,8,11,8,12,8,13,8,14,8,15,8,17,8,18,
8,19,8,20,8,21,8,22,8,23,8,24,8,25,8,26,8,27,
8,30,8,31,8,32,8,33,8,34,8,35,8,36,8,37,8,38,8,39,
9,4,9,7,9,12,9,13,9,14,9,15,9,16,9,17,9,18,9,19,9,20,9,21,9,22,9,23,9,24,9,25,
9,26,9,27,9,28,9,29,9,30,9,31,9,32,9,33,9,34,9,35,9,36,9,37,9,38,9,39,
10,4,10,5,10,6,10,7,10,8,10,9,10,10,10,11,10,12,10,13,10,14,10,15,10,16,10,17,10,18,
10,19,10,20,10,21,10,22,10,23,10,24,10,25,10,26,10,27,10,28,10,29,
10,30,10,31,10,32,10,33,10,34,10,35,10,36,10,38,10,39,
11,5,11,6,11,7,11,8,11,9,11,10,11,11,11,12,11,13,11,14,11,15,11,16,11,17,11,18,
11,19,11,27,11,28,11,29,11,30,11,31,11,32,11,33,11,34,11,35,11,36,11,38,11,39,
12,5,12,8,12,9,12,10,12,12,12,13,12,14,12,15,12,16,12,17,12,28,12,29,
12,30,12,31,12,32,12,33,12,34,12,35,12,36,12,37,
13,5,13,6,13,7,13,8,13,9,13,10,13,11,13,12,13,13,13,14,13,15,13,16,13,17,
13,28,13,29,13,30,13,31,13,32,13,33,13,34,13,35,13,36,13,37,13,38,
14,9,14,8,14,10,14,11,14,12,14,13,14,14,14,15,14,16,14,17,
14,28,14,29,14,30,14,31,14,32,14,33,14,34,14,35,14,36,14,37,14,38,
15,12,15,13,15,14,15,15,15,16,15,17,
15,28,15,29,15,30,15,31,15,32,15,33,15,34,15,35,
16,9,16,10,16,11,16,12,16,13,16,14,16,15,16,16,16,17,16,18,
16,19,16,27,16,28,16,29,16,30,16,31,16,32,16,35,16,36,16,37,
17,9,17,10,17,12,17,13,17,14,17,15,17,16,17,17,17,18,17,19,
17,20,17,21,17,22,17,23,17,24,17,25,17,26,17,27,17,28,17,29,
17,30,17,31,17,35,17,36,17,37,
18,10,18,12,18,13,18,14,18,15,18,16,18,17,18,18,18,19,
18,20,18,21,18,22,18,23,18,24,18,25,18,26,18,27,18,28,18,29,18,35,18,36,
19,24,20,23,20,24,20,25,
}
-- 初始可以行走的点
self.grids = {}
local rc, r, c
for i=1,#points,2 do
r,c = points[i],points[i+1]
rc = r * 100 + c
self.grids[rc] = {
rc = rc,
r = r,
c = c,
}
end
end
-- 是否存在该点
function MyGameScene:isInvalidPoint(rc)
return self.grids[rc]
end
-- 查找指定的点是否在列表中
local function findPoint(ps, rc)
for _, p in ipairs(ps) do
if p.rc == rc then
return p
end
end
return nil
end
-- 计算两点之间的距离
local function distance(p1, p2)
local x1, y1 = 0, 0
if p1 >= 1000 then
x1, y1 = p1 % 100, math.floor(p1 / 100)
else
x1, y1 = p1 % 10, math.floor(p1 / 10)
if y1 == 2 or y1 == 4 then
x1 = x1 + 0.5
end
end
local x2, y2 = 0, 0
if p2 >= 1000 then
x2, y2 = p2 % 100, math.floor(p2 / 100)
else
x2, y2 = p2 % 10, math.floor(p2 / 10)
if y2 == 2 or y2 == 4 then
x2 = x2 + 0.5
end
end
return math.sqrt((x1-x2)^2 + (y1 - y2)^2)
end
-- 将点位按f值升序
local function sortPointAsc(ps)
table.sort(ps, function(p1, p2)
return p1.f < p2.f
end)
end
function MyGameScene:findPath(from,dest)
if from == dest then
return {}
end
local dp = nil -- 目标值
local rc = nil
local g = nil
local h = nil
local np = nil
local opens = {
{
rc = from,
g = 0, -- 当前节点到起始点的估计
h = nil, -- 当前点到终点的估计
f = 0,
from = nil, -- 该点的前一格点
wc = 0, -- 已移动的格子数
}
}-- 开放列表
local closes = {} -- 关闭列表
while #opens > 0 do
cp = opens[1]
-- 获取附近的点
for _, ofs in ipairs(NearGridOffsets) do
rc = cp.rc + ofs
-- 目标点
if rc == dest then
dp = {rc = dest, from = cp, wc = cp.wc+1}
break
end
-- 是否存在该点,并且不在关闭列表中
if self:isInvalidPoint(rc) and not findPoint(closes,rc) then
g = distance(cp.rc,rc) + cp.g -- 到该点所需要的消耗值
np = findPoint(opens,rc) -- 是否在开放列表中
if np then --如果存在
-- 比较f值
f = np.h + g
--[[
当新的cp点到 rc 该点所f消耗少,把新的cp则替换之前的form点
]]--
if f < np.f then
np.f = f
np.g = g
np.from = cp
end
else
-- 不存在放入开放列表中
h = distance(rc, dest)
opens[#opens + 1] = {
rc = rc,
g = g,
h = h,
f = g + h,
from = cp,
wc = cp.wc+1,
}
end
end
end
-- 找到了目标点
if dp then
break
end
-- 将该点从开放列表中移除
table.remove(opens, 1)
closes[#closes+1] = cp
sortPointAsc(opens)
end
if dp == nil then
return {}
end
-- 路径
local path = {}
repeat
path[#path + 1] = dp.rc
dp = dp.from
until dp == nil or dp.rc == from
-- 将数据反序
local endIndx = #path
for i = 1, endIndx do
if i >= endIndx then
break
end
path[endIndx], path[i] = path[i], path[endIndx]
endIndx = endIndx - 1
end
return path
end