原理在网上已经有相关文章,就不补充了,因为一直在网上搜不到用lua实现的a星算法,故有下文(只有关键的代码)。

    local openList = {}
    local closeList = {} 
    local opcount = 0
    local clcount = 0

    local newx,newy --新坐标
    local step = 0 --移动步数
    local predir = nil --原移动方向
    local prefns = nil 
    local idx = 1 --新节点的索引
    local num = 1 --openList中表个数

    local function setOpenList(direction)

        local id = p.mapLayer:tileGIDAt(ccp(newx,newy))
        if id == 0 then           
            for k,v in pairs(openList) do
                if newx == v.point.x and newy == v.point.y then
                    return
                end
            end
            for k,v in pairs(closeList) do
                if newx == v.point.x and newy == v.point.y then
                    return
                end
            end
            opcount = opcount + 1
            H = math.abs(desx - newx) + math.abs(desy - newy)
            openList[opcount] = {}
            openList[opcount].point = {x=newx,y=newy} 
            openList[opcount].go = step 
            openList[opcount].fns = step + H
            openList[opcount].dir = direction
            if H == 0 then
                step = 0
                clcount = clcount + 1
                closeList[clcount] = openList[opcount]
                p.spriteX,p.spriteY = p.toOpenGLXY(openList[opcount].point.x,openList[opcount].point.y)
            end                
        end
    end
    --上下左右探索
    local function explore()
        --up
        newx = srcx
        newy = srcy - 1        
        if newy > -1 then
            if predir ~= "down" then
                setOpenList("up")
            end
        end
        --right
        newx = srcx + 1
        newy = srcy
        if newx < s.width then
            if predir ~= "left" then
                setOpenList("right")
            end
        end
        --left
        newx = srcx - 1
        newy = srcy
        if newx > -1 then
            if predir ~= "right" then
                setOpenList("left")
            end
        end
        --down
        newx = srcx
        newy = srcy + 1
        if newy < s.height then
            if predir ~= "up" then
                setOpenList("down")
            end
        end
    end
    local function setCloseList()
        for k,v in pairs(openList) do
            if k == 1 then
                prefns = v.fns
            end
            if v.fns <= prefns then
                idx = k
                prefns = v.fns
            end
            if k == num then
                srcx = openList[idx].point.x
                srcy = openList[idx].point.y                
                predir = openList[idx].dir
                clcount = clcount + 1
                closeList[clcount] = openList[idx]
                step = openList[idx].go
                table.remove(openList,idx)
                opcount = opcount - 1
            end
        end
    end
    --获取closelist
    while num ~= 0 do
        step = step + 1
        explore()
        if step == 0 then
            break
        end
        num = table.getn(openList)
        setCloseList()       
    end
    --播放动作
    local function runPlayer()
        --获取最佳路径
        local nNum = table.getn(closeList)
        local srcx,srcy,desx,desy,go
        local v = closeList[nNum]
        srcx,srcy = v.point.x,v.point.y
        go = v.go
        for k=nNum-1,1,-1 do
            local v = closeList[k]            
            desx,desy = v.point.x,v.point.y                
            local H = math.abs(desx - srcx) + math.abs(desy - srcy)
            if H > 1 or v.go ~= go - 1 then
                table.remove(closeList,k)
            else
                srcx,srcy = desx,desy
                go = v.go
            end
        end
        --播放动作
        local newx,newy
        local ctime = 0.3
        for k,v in pairs(closeList) do
            local delay = CCDelayTime:create((ctime+0.2) *(k-1))
            local x,y = p.toOpenGLXY(v.point.x,v.point.y)     
            local moveTo = CCMoveTo:create(ctime,ccp(x,y))
            local seq = CCSequence:createWithTwoActions(delay,moveTo)
            p.sprite:runAction(seq)
        end
    end
    if step == 0 then
        runPlayer()
    else
        print("不可到达",desx,desy,id)
    end

更多推荐