HappyCoding:] ChildhoodAndy

思维世界的发展,在某种意义上说,就是对惊奇的不断摆脱。——爱因斯坦

QuickCocos2dx创建描边效果

| Comments

QuickCocos2dx创建描边效果

@[quick|cocos2d|描边]


参考:


CCRenderTexture这个类平时没怎么用过,想不到用TA来创建描边效果轻松并且效果也还不错。

上面2个帖子的实现,抛开一个c++,一个oc语言来看,我发现思路其实是一样的,这里我翻译了成quick的lua版本,并在代码中相应做了些注释,朋友们可以看下。

描边函数
-- @param:node 欲描边的显示对象

-- @param:strokeWidth 描边宽度

-- @param:color 描边颜色

-- @param:opacity 描边透明度

function createStroke(node, strokeWidth, color, opacity)
    local w = node:getTexture():getContentSize().width + strokeWidth * 2
    local h = node:getTexture():getContentSize().height + strokeWidth * 2
    local rt = CCRenderTexture:create(w, h)

    -- 记录原始位置

    local originX, originY = node:getPosition()
    -- 记录原始颜色RGB信息

    local originColorR = node:getColor().r
    local originColorG = node:getColor().g
    local originColorB = node:getColor().b
    -- 记录原始透明度信息

    local originOpacity = node:getOpacity()
    -- 记录原始是否显示

    local originVisibility = node:isVisible()
    -- 记录原始混合模式

    local originBlend = node:getBlendFunc()

    -- 设置颜色、透明度、显示

    node:setColor(color)
    node:setOpacity(opacity)
    node:setVisible(true)
    -- 设置新的混合模式

    local blendFuc = ccBlendFunc:new()
    blendFuc.src = GL_SRC_ALPHA
    blendFuc.dst = GL_ONE
    -- blendFuc.dst = GL_ONE_MINUS_SRC_COLOR

    node:setBlendFunc(blendFuc)

    -- 这里考虑到锚点的位置,如果锚点刚好在中心处,代码可能会更好理解点

    local bottomLeftX = node:getTexture():getContentSize().width * node:getAnchorPoint().x + strokeWidth 
    local bottomLeftY = node:getTexture():getContentSize().height * node:getAnchorPoint().y + strokeWidth

    local positionOffsetX = node:getTexture():getContentSize().width * node:getAnchorPoint().x - node:getTexture():getContentSize().width / 2
    local positionOffsetY = node:getTexture():getContentSize().height * node:getAnchorPoint().y - node:getTexture():getContentSize().height / 2

    local rtPosition = ccp(originX - positionOffsetX, originY - positionOffsetY)

    rt:begin()
    -- 步进值这里为10,不同的步进值描边的精细度也不同

    for i = 0, 360, 10 do
        -- 这里解释了为什么要保存原来的初始信息

        node:setPosition(ccp(bottomLeftX + math.sin(degrees2radians(i)) * strokeWidth, bottomLeftY + math.cos(degrees2radians(i)) * strokeWidth))
        node:visit()
    end
    rt:endToLua()

    -- 恢复原状

    node:setPosition(originX, originY)
    node:setColor(ccc3(originColorR, originColorG, originColorB))
    node:setBlendFunc(originBlend)
    node:setVisible(originVisibility)
    node:setOpacity(originOpacity)

    rt:setPosition(rtPosition)

    return rt
end

补充

弧度与角度转换函数
function degrees2radians(angle)
    return angle * 0.01745329252
end

function radians2degrees(angle)
    return angle * 57.29577951
end

举个例子

测试例子
-- 文本、图片一样,这里用文本举个例子

local quickLabel = ui.newTTFLabel({
        text = "QuickCocos2dX-createStroke",
        color = display.COLOR_RED,
        size = 60,
        align = ui.TEXT_ALIGN_CENTER,
        x = display.cx,
        y = display.cy + 150
    }):addTo(self, 1)
    
local  renderTexture = createStroke(quickLabel, 4, ccc3(0xca, 0xa5, 0x5f), 100)
-- 设置反锯齿

renderTexture:getSprite():getTexture():setAntiAliasTexParameters()
self:addChild(renderTexture, quickLabel:getZOrder()-1)

这样的方法,会drawcall2次。

群里有朋友提到,如果文本改变,那下方的描边如何做?

那对应的描边renderTexture也需要改变,我想是得先remove掉然后重新创建纹理,那各位可以简单封装下,当文本重新setString的时候,相应去创建下方的描边纹理就可以了。

最后

如果代码有问题或者其他疑问,欢迎一起探讨学习:)

Comments

comments powered by Disqus