<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
>
<channel>
	<title>bogey</title>
	<link>https://bogey.wodemo.net/</link>
        <item>
        <title><![CDATA[lua - Bit操作]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/527338]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Mon, 30 Dec 2019 14:49:59 +0800]]></pubDate>
        <description><![CDATA[```lua
local Bit = {}

local cpu = tonumber(CPU)

local function bitToNum(bit)
    local offset = 0
    local num = 0
    if bit[1] == 1 then
        offset = 1
    end
    for i = 1, cpu do
        num = num + (2 ^ (cpu - i)) * ((bit[i] + offset) % 2)
    end
    if offset == 1 then
        num = -1 - num
    end
    return num
end

local function numToBit(num)
    local offset = 0
    if num &lt; 0 then
        offset = 1
        num = -1 - num
    end
    local bit = {}
    for i = 1, cpu do
        bit[cpu - i + 1] = (num + offset) % 2
        num = math.modf(num / 2)
    end
    return bit
end

--[[
    @desc: 转换为bit表
    author:Bogey
    time:2019-12-04 11:45:26
    --@num: 
    @return:
]]
function Bit.toBit(num)
    return numToBit(num)
end

function Bit.toNum(bit)
    return bitToNum(bit)
end

--[[
    @desc: 转换为16进制，不带0x
    author:Bogey
    time:2019-12-04 11:45:43
    --@num: 
    @return:
]]
function Bit.toHex(num)
    local hexStr = &quot;0123456789ABCDEF&quot;
    local bit = numToBit(num)
    local strs = {}
    for i = 1, cpu, 4 do
        local index = bit[i] * 8 + bit[i + 1] * 4 + bit[i + 2] * 2 + bit[i + 3] * 1 + 1
        strs[#strs + 1] = string.sub(hexStr, index, index)
    end
    return string.match(table.concat(strs), &quot;^0*(.+)&quot;)
end

--[[
    @desc: 非
    author:Bogey
    time:2019-12-04 11:46:12
    --@num: 
    @return:
]]
function Bit.bnot(num)
    local bit = numToBit(num)
    for i = 1, cpu do
        bit[i] = (bit[i] + 1) % 2
    end
    return bitToNum(bit)
end

--[[
    @desc: 与
    author:Bogey
    time:2019-12-04 11:46:21
    --@args: 
    @return:
]]
function Bit.band(...)
    local function band(aBit, bBit)
        local result = {}
        for i = 1, cpu do
            result[i] = (aBit[i] == 1 and bBit[i] == 1) and 1 or 0
        end
        return result
    end

    local count = select(&quot;#&quot;, ...)
    if count &gt; 0 then
        local r = numToBit(select(1, ...))
        for i = 2, count do
            r = band(r, numToBit(select(i, ...)))
        end
        return bitToNum(r)
    end
end

--[[
    @desc: 或
    author:Bogey
    time:2019-12-04 11:46:29
    --@args: 
    @return:
]]
function Bit.bor(...)
    local function bor(aBit, bBit)
        local result = {}
        for i = 1, cpu do
            result[i] = (aBit[i] == 1 or bBit[i] == 1) and 1 or 0
        end
        return result
    end

    local count = select(&quot;#&quot;, ...)
    if count &gt; 0 then
        local r = numToBit(select(1, ...))
        for i = 2, count do
            r = bor(r, numToBit(select(i, ...)))
        end
        return bitToNum(r)
    end
end

--[[
    @desc: 异或
    author:Bogey
    time:2019-12-04 11:46:36
    --@args: 
    @return:
]]
function Bit.bxor(...)
    local function bxor(aBit, bBit)
        local result = {}
        for i = 1, cpu do
            result[i] = (aBit[i] == bBit[i]) and 0 or 1
        end
        return result
    end

    local count = select(&quot;#&quot;, ...)
    if count &gt; 0 then
        local r = numToBit(select(1, ...))
        for i = 2, count do
            r = bxor(r, numToBit(select(i, ...)))
        end
        return bitToNum(r)
    end
end

--[[
    @desc: 左移
    author:Bogey
    time:2019-12-04 11:46:47
    --@num:
	--@offset: 
    @return:
]]
function Bit.lshift(num, offset)
    offset = offset % cpu
    local bit = numToBit(num)
    for i = 1, cpu do
        bit[i] = bit[i + offset] or 0
    end
    return bitToNum(bit)
end

--[[
    @desc: 右移
    author:Bogey
    time:2019-12-04 11:46:55
    --@num:
	--@offset: 
    @return:
]]
function Bit.rshift(num, offset)
    offset = offset % cpu
    local bit = numToBit(num)
    for i = cpu, 1, -1 do
        bit[i] = bit[i - offset] or 0
    end
    return bitToNum(bit)
end

return Bit]]></description>
    </item>
        <item>
        <title><![CDATA[lua - 文字和数字互转]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/521881]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Fri, 02 Aug 2019 16:29:17 +0800]]></pubDate>
        <description><![CDATA[```lua
--[[
    @desc: 数字转为ASCII码表示的字符串
    author:BogeyRuan
    time:2019-07-11 14:56:19
    --@num: 
    --@long: 转为多少个字节的字符，默认为动态长度
    @return:
]]
function string.numToAscii(num, long)
    local str = &quot;&quot;
    local asciiNum = num % 256
    while asciiNum &gt;= 0 and num &gt; 0 do
        str = string.char(asciiNum) .. str
        num = math.floor(num / 256)
        asciiNum = num % 256
    end
    if long then
        if #str &gt; long then
            str = string.sub(str, -long, -1)
        else
            local dis = long - #str
            for i = 1, dis do
                str = string.char(0) .. str
            end
        end
    end

    return str
end

--[[
    @desc: ASCII码转为数字
    author:BogeyRuan
    time:2019-07-11 15:49:03
    --@str: 
    @return:
]]
function string.asciiToNum(str)
    local num = 0
    for i = 1, #str do
        local s = string.sub(str, -i, -i)
        num = num + string.byte(s) * (256 ^ (i - 1))
    end
    return num
end]]></description>
    </item>
        <item>
        <title><![CDATA[lua - 贝塞尔曲线]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/520066]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Fri, 21 Jun 2019 15:03:33 +0800]]></pubDate>
        <description><![CDATA[```lua
local tableInsert = table.insert
local mathPow = math.pow
local ipairs = ipairs

local function YangHuiR3(line)
    local s = 1
    local nums = {1}
    for j = 1, line - 1 do
        s = (line - j) * s / j
        tableInsert(nums, s)
    end
    return nums
end

local function point(x, y)
    return {x = x, y = y}
end

--[[
    @desc: 根据控制点返回贝塞尔曲线
    author:BogeyRuan
    time:2019-06-21 11:57:36
    --@points: 控制点
	--@segments: 采样，越大越平滑
    @return:
]]
local function bezier(points, segments)
    local pointNum = #points
    local nums = YangHuiR3(pointNum)
    local results = {points[1]}
    for i = 1, segments do
        local t = i / segments
        local x = 0
        local y = 0
        for k,v in ipairs(points) do
            x = x + nums[k] * mathPow(1 - t, pointNum - k) * mathPow(t, k - 1) * v.x
            y = y + nums[k] * mathPow(1 - t, pointNum - k) * mathPow(t, k - 1) * v.y
        end
        tableInsert(results, point(x, y))
    end
    return results
end

return bezier]]></description>
    </item>
        <item>
        <title><![CDATA[lua - 三次样条插值曲线]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/520065]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Fri, 21 Jun 2019 15:01:22 +0800]]></pubDate>
        <description><![CDATA[```lua
local tableInsert = table.insert
local tablesort = table.sort
local ipairs = ipairs
local pairs = pairs
local tonumber = tonumber

local function point(x, y)
    return {x = x, y = y}
end

local function valuesOfKey(hashtable, key)
    local values = {}
    for k,v in pairs(hashtable) do
        if v[key] then
            values[k] = v[key]
        end
    end
    return values
end

--[[
    @desc: 根据点返回三次样条曲线
    author:BogeyRuan
    time:2019-06-21 14:38:56
    --@points: 
    @return:
]]
local function spline(points)
    assert(#points &gt;= 2, &quot;A minimum of two points&quot;)
    tablesort(points, function (a, b)
        return a.x &lt; b.x
    end)

    local xs = valuesOfKey(points, &quot;x&quot;)
    local ys = valuesOfKey(points, &quot;y&quot;)
    local ks = {}
    for i,v in ipairs(xs) do
        ks[i] = 0
    end

    local function zeroMat(r, c)
        local A = {}
        for i = 1, r do
            A[i] = {}
            for j = 1, c do
                A[i][j] = 0
            end
        end
        return A
    end

    local function swapRows(m, k, l)
        local p = m[k]
        m[k] = m[l]
        m[l] = p
    end

    local function maxMin(tb)
        local max, min
        for k,v in pairs(tb) do
            local value = tonumber(v) or 0
            if not max or max &lt; value then
                max = value
            end
            if not min or min &gt; value then
                min = value
            end
        end
        return max, min
    end

    local function solve(A, ks)
        local m = #A
        for k = 1, m do
            local i_max = 0
            local vali
            for i = k, m do
                if not vali or A[i][k] &gt; vali then
                    i_max = i
                    vali = A[i][k]
                end
            end
            swapRows(A, k, i_max)
            for i = k + 2, m do
                for j = k + 2, m + 1 do
                    A[i][j] = A[i][j] - A[k][j] * (A[i][k] / A[k][k])
                end
                A[i][k] = 0
            end
        end
        for i = m, 1, -1 do
            local v = A[i][m + 1] / A[i][i]
            ks[i] = v
            for j = i, 1, -1 do
                A[j][m + 1] = A[j][m + 1] - A[j][i] * v
                A[j][i] = 0
            end
        end
        return ks
    end

    local function getNaturalKs(ks)
        local n = #xs
        local A = zeroMat(n, n + 1)

        for i = 2, n - 1 do
            A[i][i - 1] = 1 / (xs[i] - xs[i - 1])
            A[i][i] = 2 * (1 / (xs[i] - xs[i - 1]) + 1 / (xs[i + 1] - xs[i]))
            A[i][i + 1] = 1 / (xs[i + 1] - xs[i])
            A[i][n + 1] = 3 * ((ys[i] - ys[i - 1]) / ((xs[i] - xs[i - 1]) * (xs[i] - xs[i - 1])) + (ys[i + 1] - ys[i]) / ((xs[i + 1] - xs[i]) * (xs[i + 1] - xs[i])))
        end
        A[1][1] = 2 / (xs[2] - xs[1])
        A[1][2] = 1 / (xs[2] - xs[1])
        A[1][n + 1] = (3 * (ys[2] - ys[1])) / ((xs[2] - xs[1]) * (xs[2] - xs[1]))
        A[n][n - 1] = 1 / (xs[n] - xs[n - 1])
        A[n][n] = 2 / (xs[n] - xs[n - 1])
        A[n][n + 1] = (3 * (ys[n] - ys[n - 1])) / ((xs[n] - xs[n - 1]) * (xs[n] - xs[n - 1]))

        return solve(A, ks)
    end

    ks = getNaturalKs(ks)

    local function at(x)
        local i = 2
        while xs[i] &lt; x do
            i = i + 1
        end
        local t = (x - xs[i - 1]) / (xs[i] - xs[i - 1])
        local a = ks[i - 1] * (xs[i] - xs[i - 1]) - (ys[i] - ys[i - 1])
        local b = -ks[i] * (xs[i] - xs[i - 1]) + (ys[i] - ys[i - 1])
        local q = (1 - t) * ys[i - 1] + t * ys[i] + t * (1 - t) * (a * (1 - t) + b * t)
        return q
    end

    local max, min = maxMin(xs)
    local points = {}
    for i = min, max do
        tableInsert(points, point(i, at(i)))
    end
    return points
end

return spline]]></description>
    </item>
        <item>
        <title><![CDATA[Cocos2dx - 根据背景高效率的生成模糊节点]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/509766]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Tue, 21 May 2019 17:30:40 +0800]]></pubDate>
        <description><![CDATA[```lua

local vsh = [[
    attribute vec4 a_position;
    attribute vec2 a_texCoord;
    attribute vec4 a_color;
    
    #ifdef GL_ES
    varying lowp vec4 v_fragmentColor;
    varying mediump vec2 v_texCoord;
    #else
    varying vec4 v_fragmentColor;
    varying vec2 v_texCoord;
    #endif
    
    void main()
    {
        gl_Position = CC_PMatrix * a_position;
        v_fragmentColor = a_color;
        v_texCoord = a_texCoord;
    }
]]

local fsh = [[
    #ifdef GL_ES
    precision mediump float;
    #endif
    
    varying vec4 v_fragmentColor;
    varying vec2 v_texCoord;
    
    uniform vec2 resolution;
    uniform float blurRadius;
    
    vec4 blur(vec2);
    
    void main(void)
    {
        vec4 col = blur(v_texCoord);
        gl_FragColor = vec4(col) * v_fragmentColor;
    }
    
    vec4 blur(vec2 p)
    {
        if (blurRadius &gt; 0.0)
        {
            vec4 col = vec4(0);
            vec2 unit = 1.0 / resolution.xy;
            
            float r = blurRadius;
            float sampleStep = 1.0;
            
            float count = 0.0;
            
            for(float x = -r; x &lt; r; x += sampleStep)
            {
                for(float y = -r; y &lt; r; y += sampleStep)
                {
                    float weight = (r - abs(x)) * (r - abs(y));
                    col += texture2D(CC_Texture0, p + vec2(x * unit.x, y * unit.y)) * weight;
                    count += weight;
                }
            }
            
            return col / count;
        }
        
        return texture2D(CC_Texture0, p);
    }
]]

local function getRealNodes(node, tb)
    local nodeType = tolua.type(node)
    if nodeType == &quot;cc.Sprite&quot; then
        table.insert(tb, node)
    elseif nodeType == &quot;ccui.Scale9Sprite&quot; then
        getRealNodes(node:getSprite(), tb)
    elseif nodeType == &quot;ccui.Text&quot; then
        getRealNodes(node:getVirtualRenderer(), tb)
    elseif nodeType == &quot;ccui.Button&quot; then
        getRealNodes(node:getVirtualRenderer(), tb)
        getRealNodes(node:getTitleRenderer(), tb)
    elseif nodeType == &quot;cc.Label&quot; then
        node:updateContent()    --先刷新内部精灵
        getRealNodes(node:getChildren()[1], tb)
    elseif nodeType == &quot;cc.RenderTexture&quot; then
        getRealNodes(node:getSprite(), tb)
    else
        table.insert(tb, node)
    end
end

--[[
    @desc: 高斯模糊[shader实现，掉帧严重]
    author:BogeyRuan
    time:2019-05-15 14:26:45
    --@node: 要变模糊的节点
	--@[radius]: 模糊半径，默认10
	--@[resolution]: 采样粒度，大多数时间不用传
    @return:
]]
function display.makeBlur(node, radius, resolution)
    local nodes = {}
    getRealNodes(node, nodes)
    for _, node in pairs(nodes) do
        if resolution == nil then
            local size = node:getContentSize()
            if size.width == 0 or size.height == 0 then
                return
            end
            resolution = cc.p(size.width, size.height)
        end
        if radius == nil then
            radius = 10
        end
    
        local glProgram = cc.GLProgram:createWithByteArrays(vsh, fsh)
        local glProgramState = cc.GLProgramState:getOrCreateWithGLProgram(glProgram)
        glProgramState:setUniformVec2(&quot;resolution&quot; , resolution)
        glProgramState:setUniformFloat(&quot;blurRadius&quot;, radius)
        node:setGLProgramState(glProgramState)
    end
end

--[[
    @desc: 截取一张指定节点指定位置的模糊截图
    author:BogeyRuan
    time:2019-05-21 15:56:15
    --@[node]: 指定的节点
    --@[rect]: 截取的范围，节点坐标
    @return: 
]]
function display.captureBlurNode(node, rect)
    local node = node or display.getRunningScene()
    -- 因为截取指定区域的函数的限制，得先把父节点和自己移动到左下角
    local parent = node:getParent()
    local parentPos
    if parent then
        parentPos = cc.p(parent:getPosition())
        local basePos = parent:convertToWorldSpace(cc.p(0, 0))
        parent:setPosition(cc.pSub(parentPos, basePos))
    end
    local nodePos = cc.p(node:getPosition())
    local nodeSize = node:getContentSize()
    local nodeAnchor = node:getAnchorPoint()
    node:setPosition(nodeAnchor.x * nodeSize.width, nodeAnchor.y * nodeSize.height)

    local pos = node:convertToWorldSpace(cc.p(0, 0))
    if rect then
        nodeSize = cc.size(rect.width, rect.height)
        pos = cc.pAdd(cc.p(rect.x, rect.y), nodePos)
    end
    local texture = cc.RenderTexture:create(nodeSize.width, nodeSize.height, cc.TEXTURE2_D_PIXEL_FORMAT_RGB_A8888, gl.DEPTH24_STENCIL8_OES)
    -- texture:setKeepMatrix(true)
    -- texture:setVirtualViewport(pos, cc.rect(0, 0, display.size), cc.rect(0, 0, cc.sizeMul(display.size, cc.Director:getInstance():getContentScaleFactor())))
    texture:beginWithClear(0, 0, 0, 0)
    node:visit()
    texture:endToLua()

    if parent then
        parent:setPosition(parentPos)
    end
    node:setPosition(nodePos)

    texture:pos(0, 0)
    local blurSp = texture:getSprite()
    local size = blurSp:getContentSize()
    blurSp:align(display.CENTER, size.width / 2, size.height / 2)
    display.makeBlur(blurSp)

    local texture2 = cc.RenderTexture:create(size.width, size.height, cc.TEXTURE2_D_PIXEL_FORMAT_RGB_A8888, gl.DEPTH24_STENCIL8_OES)
    texture2:beginWithClear(0, 0, 0, 0)
    blurSp:visit()
    texture2:endToLua()

    return texture2
end
```## 踩坑指南
RenderTexture默认裁剪的位置之类的是没有问题的，setVirtualViewport却没有裁剪到正确的纹理是因为要裁剪的节点的父节点的位置问题，具体情况很复杂。

```cpp
void Node::visit()
{
    auto renderer = Director::getInstance()-&gt;getRenderer();
    Mat4 parentTransform = Director::getInstance()-&gt;getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    visit(renderer, parentTransform, true);
}
```

从Node的visit方法开始就出现坑了，默认返回的parentTransform和真实的transform是对不上的，导致要截图的节点的区域是错误的
所以修改起来就是直接把要截图的节点的位置和其父节点的位置都设置为相对世界坐标下的(0,0)点]]></description>
    </item>
        <item>
        <title><![CDATA[lua - 根据分隔符配置拆分字符]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/479852]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Wed, 16 May 2018 10:24:49 +0800]]></pubDate>
        <description><![CDATA[```lua
--[[
    @desc: 根据传入的成对的字符串拆分文字
    author:BogeyRuan
    time:2019-06-17 11:04:07
    --@str: 要拆分的文字
	--@config: 成对的字符串集合，如{&quot;#*&quot;, &quot;()&quot;}
    @return: 返回拆出来的文字，并附加文字被包含的索引,普通文字索引为配置数加1
    @example: string.splitByConfig(&quot;ab#cde*fg&quot;, {&quot;#*&quot;})
    @result: {{text = &quot;ab&quot;, index = 2}, {text = &quot;cde&quot;, index = 1}, {text = &quot;fg&quot;, index = 2}}
]]
function string.splitByConfig(str, config)
    local configNum = #config
    local splitIndex = {}
    for i, v in ipairs(config) do
        local split_1 = {value = string.sub(v, 1, 1), tag = i, type = 1}
        local split_2 = {value = string.sub(v, -1, -1), tag = i, type = 2}

        local index_1, index_2 = string.find(str, string.format(&quot;%%b%s&quot;, v), 1)
        while index_1 do
            table.insert(splitIndex, {index = index_1, value = split_1})
            table.insert(splitIndex, {index = index_2, value = split_2})
            index_1, index_2 = string.find(str, string.format(&quot;%%b%s&quot;, v), index_1 + 1)
        end
    end
    table.sort(splitIndex, function(a, b)
        return a.index &lt; b.index
    end)

    local strTemp = {}
    local splitStack = {{tag = configNum + 1}}
    local tempStr = &quot;&quot;
    local index = 1
    for i = 1, #str do
        local split = splitIndex[index]
        if split and i == split.index then
            if tempStr ~= &quot;&quot; then
                table.insert(strTemp, {str = tempStr, index = splitStack[#splitStack].tag})
            end
            if split.value.type == 1 then
                table.insert(splitStack, split.value)
            end
            if split.value.type == 2 then
                table.remove(splitStack, #splitStack)
            end
            index = index + 1
            tempStr = &quot;&quot;
        else
            tempStr = tempStr .. string.sub(str, i, i)
        end
    end
    if tempStr ~= &quot;&quot; then
        table.insert(strTemp, {str = tempStr, index = configNum + 1})
    end
    return strTemp
end
```lua
-- 根据配置拆分字符（老版本）
function string.splitByConfig(str, config)
    local configNum = #config
    local strTemp = {}
    local indexs = {}   --所有特殊字符下标合集
    local index = 1
    while true do
        local flag = true
        local realHead, realEnd, indexInConfig
        for i,v in ipairs(config) do
            local tempHead, tempEnd = string.find(str, string.format(&quot;%%b%s&quot;, v), index)
            if tempHead then
                flag = false
                if (not realHead) or realHead &gt; tempHead then
                    realHead, realEnd, indexInConfig = tempHead, tempEnd, i
                end
            end
        end
        if flag then
            break
        else
            index = realEnd + 1
            table.insert(indexs, {i = realHead, j = realEnd, index = indexInConfig})
        end
    end

    if table.isEmpty(indexs) then
        return {{text = str, index = configNum + 1}}
    end

    for i,v in ipairs(indexs) do
        local info = indexs[i - 1]
        local lastIndex
        if info then
            lastIndex = info.j + 1
        else
            lastIndex = 1
        end

        local normalStr = string.sub(str, lastIndex, v.i - 1)
        if normalStr and not string.isEmpty(normalStr) then
            table.insert(strTemp, {text = normalStr, index = configNum + 1})
        end

        local specialStr = string.sub(str, v.i, v.j)
        specialStr = string.sub(specialStr, 2, -2)
        if specialStr and not string.isEmpty(specialStr) then
            table.insert(strTemp, {text = specialStr, index = v.index})
        end
    end

    local lastIndex = indexs[#indexs].j + 1
    local normalStr = string.sub(str, lastIndex)
    if normalStr and not string.isEmpty(normalStr) then
        table.insert(strTemp, {text = normalStr, index = configNum + 1})
    end
    
    return strTemp
end]]></description>
    </item>
        <item>
        <title><![CDATA[lua - A星寻路]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/477037]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Thu, 12 Apr 2018 16:06:38 +0800]]></pubDate>
        <description><![CDATA[. AStar.lua```lua
local AStar = {}

-- 配置参数，地图大小，方向数量，步长
local max = 20
local dir = 4
local step = 1

local function isEmptyTable(tb)
    if not tb or type(tb) ~= &quot;table&quot; then
        return true
    end
    for k, v in pairs(tb) do
        return false
    end
    return true
end

local function p(x, y)
    return {x = x, y = y}
end

function AStar:init(poss)
    -- 阻挡点缓存，优先判断阻挡点缓存
    if not self.unDots then
        self.unDots = {}
    end

    self.dots = {}
    self.open = {}
    self.close = {}
    self.basePos = {}
    for i,v in ipairs(poss) do
        self.open[i] = {}
        self.close[i] = {}
        self.basePos[i] = v
    end
end

function AStar:addDot(pos, pDot, type, dis)
    local real = self:getReal(pos, pDot)
    local fore = self:getFore(pos, type, 3, dis)
    table.insert(self.dots, {
        pos = pos,
        pDot = pDot,
        real = real,
        fore = fore
    })
    self.open[type][#self.dots] = true
end

function AStar:getReal(pos, pDot)
    local real = 0
    if pDot then
        local x, y = pos.x - self.dots[pDot].pos.x, pos.y - self.dots[pDot].pos.y
        real = self.dots[pDot].real + math.sqrt(x * x + y * y)
    end
    return real
end

--估值，fun = 1，最短; fun = 3, 最长; fun = 2, 中等
function AStar:getFore(pos, type, fun, dis)
    local fore = max + max
    local realType = type + dis
    if realType &gt; #self.basePos then
        realType = 1
    elseif realType &lt; 0 then
        realType = #self.basePos
    end
    local targetPos = self.basePos[realType]
    local x, y = math.abs(pos.x - targetPos.x), math.abs(pos.y - targetPos.y)
    if fun == 1 then
        fore = math.sqrt(x * x + y * y)
    elseif fun == 2 then
        if x &gt; y then
            fore = math.sqrt(step * step * 2) * y + x - y
        else
            fore = math.sqrt(step * step * 2) * x + y - x
        end
    else
        fore = x + y
    end
    return fore
end

function AStar:addPos(type, index)
    self.open[type][index] = true
    self.close[type][index] = nil
end

function AStar:delPos(type, index)
    self.open[type][index] = nil
    self.close[type][index] = true
end

function AStar:addUnDot(pos)
    if not self.unDots[pos.x] then
        self.unDots[pos.x] = {}
    end
    self.unDots[pos.x][pos.y] = true
end

function AStar:delUnDot(pos)
    if self.unDots[pos.x] and self.unDots[pos.x][pos.y] then
        self.unDots[pos.x][pos.y] = nil
        if isEmptyTable(self.unDots[pos.x]) then
            self.unDots[pos.x] = nil
        end
    end
end

function AStar:getMinDot(type)
    local dot, index
    for k, _ in pairs(self.open[type]) do
        if not dot then
            dot = self.dots[k]
            index = k
        else
            if self.dots[k].real + self.dots[k].fore &lt; dot.real + dot.fore then
                dot = self.dots[k]
                index = k
            end
        end
    end
    return dot, index
end

function AStar:isPosInTb(tb, pos)
    for k, _ in pairs(tb) do
        if self.dots[k].pos.x == pos.x and self.dots[k].pos.y == pos.y then
            return true, k
        end
    end
    return false
end

function AStar:pathFind(poss, checkFunc)
    if not checkFunc then
        poss = self:initPos()
    end

    self.checkFunc = checkFunc
    self:init(poss)

    local startTime = os.clock()
    local paths = {}
    for type = 1, #poss - 1 do
        local nextType = type + 1
        if nextType &gt; #poss then
            nextType = 1
        end
        self.dots = {}
        self.open[type] = {}
        self.open[nextType] = {}
        self.close[type] = {}
        self.close[nextType] = {}

        self:addDot(self.basePos[type], nil, type, 1)
        self:addDot(self.basePos[nextType], nil, nextType, -1)

        local path
        while true do
            if self:findAroundByTb(type, 1) then
                break
            end
            path = self:checkPath(type, nextType)
            if path then
                break
            end
            if self:findAroundByTb(nextType, -1) then
                break
            end
            path = self:checkPath(type, nextType)
            if path then
                break
            end
        end
        table.insert(paths, path)
    end
    
    local path = self:margePath(paths)
    print(os.clock() - startTime)
    print(isEmptyTable(path))
    return path
end

function AStar:findAroundByTb(type, dis)
    if not isEmptyTable(self.open[type]) then
        local dot, index = self:getMinDot(type)
        self:delPos(type, index)
        for i = 1, dir do
            local pos = self:findAround(type, dot.pos, index, i)
            if pos then
                self:addDot(pos, index, type, dis)
            end
        end
    else
        return true
    end
end

function AStar:checkPath(type, nextType)
    local a, b
    local minReal = max + max
    for i,v in pairs(self.open[type]) do
        for j,k in pairs(self.open[nextType]) do
            if self.dots[i].pos.x == self.dots[j].pos.x and self.dots[i].pos.y == self.dots[j].pos.y then
                local doti = self.dots[i]
                local dotj = self.dots[j]
                local nowReal = doti.real - self.dots[doti.pDot or 1].real + dotj.real - self.dots[dotj.pDot or 1].real
                if nowReal &lt; minReal then
                    minReal = nowReal
                    a = i
                    b = j
                end
            end
        end
    end
    if not (a and b) then
        return
    end
    local path = self:getPath(self.dots[a], self.dots[b], type, nextType)
    return path
end

function AStar:getPath(aDot, bDot, type, nextType)
    local path1 = {}
    while aDot.pDot do
        table.insert(path1, aDot.pos)
        aDot = self.dots[aDot.pDot]
    end
    table.insert(path1, self.basePos[type])

    local path2 = {}
    while bDot.pDot do
        table.insert(path2, bDot.pos)
        bDot = self.dots[bDot.pDot]
    end
    table.insert(path2, self.basePos[nextType])

    for i = 2, #path1 do
        table.insert(path2, 1, path1[i])
    end

    return path2
end

function AStar:margePath(paths)
    local path = {}
    for i,v in ipairs(paths) do
        for j,k in ipairs(v) do
            if not (i ~= 1 and j == 1) then
                table.insert(path, k)
            end
        end
    end
    return path
end

function AStar:findAround(type, pos, index, dir)
    local x = pos.x
    local y = pos.y
    if dir == 1 then
        x = x - step
    elseif dir == 2 then
        y = y + step
    elseif dir == 3 then
        x = x + step
    elseif dir == 4 then
        y = y - step

    elseif dir == 5 then
        x = x - step
        y = y + step
    elseif dir == 6 then
        x = x - step
        y = y - step
    elseif dir == 7 then
        x = x + step
        y = y + step
    elseif dir == 8 then
        x = x + step
        y = y - step
    end

    if x &lt; 1 or x &gt; max or y &lt; 1 or y &gt; max then
        return
    end

    local nowPos = p(x, y)
    local bool, idx = self:isPosInTb(self.open[type], nowPos)
    if bool then
        local real = self:getReal(nowPos, index)
        if real &lt; self.dots[idx].real then
            self.dots[idx].real = real
            self.dots[idx].pDot = index
        end
        return
    end
    
    bool, idx = self:isPosInTb(self.close[type], nowPos)
    if bool then
        local real = self:getReal(nowPos, index)
        if real &lt; self.dots[idx].real then
            self.dots[idx].pDot = index
            self.dots[idx].real = real
            self:addPos(type, idx)
        end
        return
    end

    if self.unDots[x] and self.unDots[x][y] then
        return
    end

    if self.checkFunc then
        if self.checkFunc(nowPos, dir) then
            return nowPos
        else
            self:addUnDot(nowPos)
        end
    elseif self.testCheck then
        if self:testCheck(nowPos) then
            return nowPos
        else
            self:addUnDot(nowPos)
        end
    end
end

-----------------cocos test
function AStar:initPos()
    self.config = {}
    self.unDots = {}
    for i = 1, max do
        for j = 1, max do
            if math.random(1, 4) == 1 then
                if not self.config[i] then
                    self.config[i] = {}
                end
                self.config[i][j] = true
            end
        end
    end
    return {p( math.floor(math.random(1, max / step) * step) , math.floor(math.random(1, max / step) * step)), p(math.floor(math.random(1, max / step) * step), math.floor(math.random(1, max / step) * step))}
end

function AStar:testCheck(pos)
    if self.config and self.config[pos.x] and self.config[pos.x][pos.y] then
        return false
    end
    return true
end

function AStar:drawPath(parent, path)
    if isEmptyTable(path) then
        return
    end

    local function isInPath(tb, x, y)
        for i,v in ipairs(tb) do
            if v.x == x and v.y == y then
                return true
            end
        end
    end

    local function isInTb(tb, x, y)
        for i,v in pairs(tb) do
            for j,k in pairs(v) do
                if self.dots[j].pos.x == x and self.dots[j].pos.y == y then
                    return true
                end
            end
        end
    end

    local node = parent:getChildByTag(666)
    if not node then
        node = cc.Node:create()
        node:setPosition(100, 100)
        parent:addChild(node, 1, 666)
    end
    local width = 20

    for x = 1, max do
        for y = 1, max do
            local drawNode = node:getChildByTag(x * max + y)
            if not drawNode then
                drawNode = cc.DrawNode:create()
                drawNode:setPosition(x * width, y * width)
                node:addChild(drawNode, 1, x * max + y)
            end
            drawNode:clear()
            if isInPath(self.basePos, x, y) then
                drawNode:drawSolidRect(cc.p(0, 0), cc.p(width, width), cc.c4f(0, 1, 0, 1))
            elseif isInPath(path, x, y) then
                drawNode:drawSolidRect(cc.p(0, 0), cc.p(width, width), cc.c4f(1, 1, 0, 1))
            elseif not self:testCheck(p(x, y)) then
                drawNode:drawSolidRect(cc.p(0, 0), cc.p(width, width), cc.c4f(0.2, 0.2, 0.2, 1))
            elseif isInTb(self.open, x, y) then
                drawNode:drawSolidRect(cc.p(0, 0), cc.p(width, width), cc.c4f(0.5, 0.7, 0.5, 1))
            elseif isInTb(self.close, x, y) then
                drawNode:drawSolidRect(cc.p(0, 0), cc.p(width, width), cc.c4f(0.5, 0.5, 0.7, 1))
            else
                drawNode:drawSolidRect(cc.p(0, 0), cc.p(width, width), cc.c4f(1, 1, 1, 1))
            end
        end
    end
end

return AStar]]></description>
    </item>
        <item>
        <title><![CDATA[lua - 把字符分割并分别打上Unicode长度标记]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/476883]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Tue, 10 Apr 2018 15:47:58 +0800]]></pubDate>
        <description><![CDATA[```lua
function stringToChars(str)
    local list = {}
    local len = string.len(str)
    local i = 1
    while i &lt;= len do
        local c = string.byte(str, i)
        local shift = 1
        if c &gt; 0 and c &lt;= 127 then
            shift = 1
        elseif (c &gt;= 192 and c &lt;= 223) then
            shift = 2
        elseif (c &gt;= 224 and c &lt;= 239) then
            shift = 3
        elseif (c &gt;= 240 and c &lt;= 247) then
            shift = 4
        end
        local char = string.sub(str, i, i + shift - 1)
        i = i + shift
		table.insert(list, {char = char, shift = shift})
    end
    return list
end]]></description>
    </item>
        <item>
        <title><![CDATA[lua - 数字转中文数字]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/468122]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Wed, 10 Jan 2018 15:31:17 +0800]]></pubDate>
        <description><![CDATA[```lua
--[[
    @desc: 数字转中文数字
    author:BogeyRuan
    time:2019-06-17 14:41:49
    --@num: 
    @return:
]]
function toChineseNumber(num)
    assert(type(num) == &quot;number&quot;, &quot;Must be a number&quot;)
    local hzNum = {&quot;零&quot;, &quot;一&quot;, &quot;二&quot;, &quot;三&quot;, &quot;四&quot;, &quot;五&quot;, &quot;六&quot;, &quot;七&quot;, &quot;八&quot;, &quot;九&quot;}
    local hzUnit = {&quot;&quot;, &quot;十&quot;, &quot;百&quot;, &quot;千&quot;}
    local hzBigUnit = {&quot;&quot;, &quot;万&quot;, &quot;亿&quot;}

    num = string.reverse(tostring(num))

    local function getString(index, data)
        local len = #data
        local str = &quot;&quot;
        for i = len, 1, -1 do
            -- 两个连续的零或者末尾零，跳过
            if data[i] == &quot;0&quot; and (data[i - 1] == &quot;0&quot; or i == 1) then
            else
                --类似一十七，省略一，读十七
                if len == 2 and i == 2 and data[i] == &quot;1&quot; and index == 1 then
                else
                    str = str .. hzNum[tonumber(data[i]) + 1]
                end

                --单位，零没有单位
                if data[i] ~= &quot;0&quot; then
                    str = str .. hzUnit[i]
                end
            end
        end
        -- 大单位
        str = str .. hzBigUnit[index]
        return str
    end

    -- 拆分成4位一段
    local numTable = {}
    local len = string.len(num)
    for i = 1, len do
        local index = math.ceil(i / 4)
        if not numTable[index] then
            numTable[index] = {}
        end
        table.insert(numTable[index], string.sub(num, i, i))
    end

    -- 组合文字
    local str = &quot;&quot;
    for i,v in ipairs(numTable) do
        local rt = getString(i, v)
        str = rt .. str
    end
    return str
end]]></description>
    </item>
        <item>
        <title><![CDATA[Material]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/437413]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Tue, 11 Apr 2017 20:17:27 +0800]]></pubDate>
        <description><![CDATA[. body-bg.png. bogey.png. bogeyicon.png. header-bg.png. icon.png. menu.png. Link.cur. Normal.cur. highlight.js]]></description>
    </item>
        <item>
        <title><![CDATA[自用wodemo皮肤]]></title>
		<link><![CDATA[https://bogey.wodemo.net/entry/403718]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Tue, 05 Jul 2016 08:24:42 +0800]]></pubDate>
        <description><![CDATA[##[Markdown代码高亮使用介绍](http://blog.csdn.net/u013553529/article/details/50629055)

##[代码高亮包下载地址](https://highlightjs.org/)##[CSS](https://bogey.wodemo.net/skin/bogey/1494512201/site.css)
##[JavaScript](https://bogey.wodemo.net/skin/bogey/1494512201/site.js)
##HTML
```html
&lt;div class=&quot;myhead&quot;&gt;
	&lt;div id=&quot;top&quot;&gt;
		&lt;span class=&quot;bogey_tx&quot;&gt;
			&lt;a href=&quot;https://bogey.wodemo.net&quot; style=&quot;display:block&quot;&gt;&lt;img src=&quot;https://bogey.wodemo.net/entry/437413/20170411/0152137dc318938e2fda2378e5fde6b8/bogeyicon.png&quot; width=&quot;40px&quot;&gt;&lt;/a&gt;
		&lt;/span&gt;
		&lt;div class=&quot;webname&quot;&gt;BOGEY&lt;/div&gt;
		&lt;span class=&quot;menu&quot;&gt;&lt;/span&gt;
		&lt;div class=&quot;notifaction-bg&quot;&gt;
			&lt;a href=&quot;https://s.wodemo.net/notification&quot;&gt;&lt;/a&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;!-- 新菜单栏 --&gt;
	&lt;div class=&quot;munu_zg&quot; style=&quot;display: none&quot;&gt;&lt;/div&gt;
	&lt;div class=&quot;munu_right&quot; style=&quot;width: 0px&quot;&gt;
		&lt;ul class=&quot;ul_box&quot;&gt;
			&lt;li&gt;
				&lt;!-- 搜索 --&gt;
				&lt;div class=&quot;search&quot;&gt;
					&lt;div class=&quot;selarch_box&quot;&gt;
						&lt;form action=&quot;/search&quot;&gt;
							&lt;input type=&quot;text&quot; name=&quot;q&quot; class=&quot;search_test&quot; maxlength=&quot;28&quot; value=&quot;请输入你想搜索的关键词吧...&quot; onfocus=&quot;if(this.value == '请输入你想搜索的关键词吧...'){this.value = ''}&quot; onblur=&quot;if(this.value == ''){ this.value = '请输入你想搜索的关键词吧...'}&quot;&gt;
						&lt;span class=&quot;sel_sc&quot;&gt;&lt;/span&gt;
						&lt;select name=&quot;all&quot; class=&quot;search_sel&quot;&gt;
							&lt;option value=&quot;0&quot;&gt;本站&lt;/option&gt;
							&lt;option value=&quot;1&quot;&gt;全站&lt;/option&gt;
						&lt;/select&gt;
						&lt;input type=&quot;submit&quot; class=&quot;search_btn&quot; value=&quot;搜索&quot;&gt;
						&lt;/form&gt;
					&lt;/div&gt;
				&lt;/div&gt;
				&lt;!-- 搜索 end--&gt;
			&lt;/li&gt;
			&lt;li&gt;
				&lt;span class=&quot;ul_box_title&quot;&gt;分类&lt;/span&gt;
				&lt;ul class=&quot;ul_sub fenlei&quot; style=&quot;display:block&quot;&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
			&lt;li&gt;
				&lt;span class=&quot;ul_box_title&quot;&gt;管理员工具&lt;/span&gt;
				&lt;ul class=&quot;ul_sub&quot;&gt;
					&lt;li&gt;&lt;a href=&quot;https://s.wodemo.net/admin&quot; target=&quot;_blank&quot;&gt;Dock&lt;/a&gt;&lt;/li&gt;
					&lt;li&gt;&lt;a href=&quot;https://s.wodemo.net/admin/site/compose&quot; target=&quot;_blank&quot;&gt;撰文&lt;/a&gt;&lt;/li&gt;
					&lt;li&gt;&lt;a href=&quot;https://s.wodemo.net/admin/site/category&quot; target=&quot;_blank&quot;&gt;分类&lt;/a&gt;&lt;/li&gt;
					&lt;li&gt;&lt;a href=&quot;https://s.wodemo.net/admin/site&quot; target=&quot;_blank&quot;&gt;站点&lt;/a&gt;&lt;/li&gt;
					&lt;li&gt;&lt;a href=&quot;https://s.wodemo.net/admin/site/skins?site_id=12321&quot; target=&quot;_blank&quot;&gt;皮肤&lt;/a&gt;
					&lt;li&gt;&lt;a href=&quot;https://s.wodemo.net/admin/stats&quot; target=&quot;_blank&quot;&gt;统计&lt;/a&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
&lt;!--			
			&lt;li&gt;
				&lt;span class=&quot;ul_box_title&quot;&gt;互动&lt;/span&gt;
				&lt;ul class=&quot;ul_sub&quot;&gt;
					&lt;li&gt;&lt;a href=&quot;#&quot; target=&quot;_blank&quot;&gt;在线留言&lt;/a&gt;&lt;/li&gt;
					&lt;li&gt;&lt;a href=&quot;#&quot; target=&quot;_blank&quot;&gt;友情链接&lt;/a&gt;&lt;/li&gt;
					&lt;li&gt;&lt;a href=&quot;#&quot; target=&quot;_blank&quot;&gt;关于我们&lt;/a&gt;&lt;/li&gt;
				&lt;/ul&gt;
			&lt;/li&gt;
--&gt;
		&lt;/ul&gt;
	&lt;/div&gt;
	&lt;!-- 新菜单栏 end --&gt;
&lt;/div&gt;
&lt;div class=&quot;back_top&quot;&gt;▲&lt;/div&gt;
```##撰文模板
```html
&lt;!-- Markdown代码高亮 --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/styles/default.min.css&quot;&gt;
&lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.9.0/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;

&lt;div id=&quot;my-entry-whole&quot;&gt;
	&lt;div id=&quot;my-entry-title&quot;&gt;{wo.entry.title}&lt;/div&gt;
	&lt;div id=&quot;my-entry-time&quot; timestamp=&quot;{wo.entry.creation.timestamp}&quot;&gt;
		{wo.entry.creation.datestr}
	&lt;/div&gt;
	&lt;div id=&quot;my-entry-main&quot;&gt;
		{wo.entry.main}
	&lt;/div&gt;
&lt;/div&gt;
{wo.entry.prevnext}
{wo.entry.comments}
{wo.site.backtohome}##首页模板
```html
{wo.site.htmlhead}
&lt;div id=&quot;mycategories&quot; style=&quot;display:none;&quot;&gt;
	{wo.site.categories}
&lt;/div&gt;
{wo.site.entries}
{wo.site.prevnext}##首页列表单行的模板
```html
&lt;a href=&quot;{wo.entry.url}&quot; target=&quot;_blank&quot;&gt;{wo.entry.title}&lt;/a&gt;&lt;span&gt;{wo.entry.creation.datestr.ymd}&lt;/span&gt;
]]></description>
    </item>
        <item>
        <title><![CDATA[酷鱼-MiniMusicPlayer.xwp]]></title>
		<link><![CDATA[https://bogey.wodemo.net/file/403098]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Fri, 01 Jul 2016 07:33:19 +0800]]></pubDate>
        <description><![CDATA[File Size: 113.68 KiB&nbsp;|&nbsp;<a href="https://bogey.wodemo.net/meta/403098">Meta</a>]]></description>
    </item>
        <item>
        <title><![CDATA[酷鱼-AP.xwp]]></title>
		<link><![CDATA[https://bogey.wodemo.net/file/403097]]></link>
		<dc:creator><![CDATA[bogey (@bogey)]]></dc:creator>
		<pubDate><![CDATA[Fri, 01 Jul 2016 07:32:31 +0800]]></pubDate>
        <description><![CDATA[File Size: 24.43 MiB&nbsp;|&nbsp;<a href="https://bogey.wodemo.net/meta/403097">Meta</a>]]></description>
    </item>
    </channel>
</rss>
