简单的A*寻路

 -- 偏移量
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

猜你喜欢

转载自blog.csdn.net/erweimac/article/details/78855980