[zz]字体、图片描边

参考:


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

举个例子

-- 文本、图片一样,这里用文本举个例子
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的时候,相应去创建下方的描边纹理就可以了。

 


Stroke example for CCLabelTTF and CCSprite.

By Alexandr Gerasimov Posted  10 months ago Comments 11

Alexandr Gerasimov

 Posts: 8

Hey guys! Several days ago i found a cocs2d-iphone examples "stroke effect for CCLabelTTF objects". Here is the link to the cocos2d-iphone forum: http://www.cocos2d-iphone.org/forum/topic/12126

I made little modifications in this example and rewrote it for c++. Here is my code:

1CCRenderTexture* createStroke(CCSprite* label, int size, ccColor3B color, GLubyte opacity)

 2 {

 3

 4    CCRenderTexture* rt = CCRenderTexture::renderTextureWithWidthAndHeight(

 5        label->getTexture()->getContentSize().width + size * 2,

 6        label->getTexture()->getContentSize().height+size * 2

 7        );

 8

 9    CCPoint originalPos = label->getPosition();

10

11    ccColor3B originalColor = label->getColor();

12

13    GLubyte originalOpacity = label->getOpacity();

14

15    bool originalVisibility = label->getIsVisible();

16

17    label->setColor(color);

18

19    label->setOpacity(opacity);

20

21    label->setIsVisible(true);

22

23    ccBlendFunc originalBlend = label->getBlendFunc();

24

25    ccBlendFunc bf = {GL_SRC_ALPHA, GL_ONE};

26

27    label->setBlendFunc(bf);

28

29    CCPoint bottomLeft = ccp(

30        label->getTexture()->getContentSize().width * label->getAnchorPoint().x + size, 

31        label->getTexture()->getContentSize().height * label->getAnchorPoint().y + size);

32

33    CCPoint positionOffset= ccp(

34        - label->getTexture()->getContentSize().width / 2,

35        - label->getTexture()->getContentSize().height / 2);

36

37    CCPoint position = ccpSub(originalPos, positionOffset);

38

39    rt->begin();

40

41    for (int i=0; i<360; i+= 15) // you should optimize that for your needs

42    {

43        label->setPosition(

44            ccp(bottomLeft.x + sin(CC_DEGREES_TO_RADIANS(i))*size, bottomLeft.y + cos(CC_DEGREES_TO_RADIANS(i))*size)

45            );

46        label->visit();

47    }

48    rt->end();

49

50    label->setPosition(originalPos);

51    label->setColor(originalColor);

52    label->setBlendFunc(originalBlend);

53    label->setIsVisible(originalVisibility);

54    label->setOpacity(originalOpacity);

55

56    rt->setPosition(position);

57

58    return rt;

59}

 


I added "opacity" property and possibility to add Stroke for all CCSprite nodes.

Example of usage:

1    CCSprite* sprite = CCSprite::spriteWithFile("some_sprite.png");

2

3    addChild(sprite);

4

5    CCRenderTexture* tex = createStroke(sprite, 2 /*size*/, ccc3(0, 255, 0)/*color*/, 50 /*opacity*/);

6

7    addChild(tex, sprite->getZOrder() - 1);

 

 

stroke.png (47.6 kB)

Alexander Belchenko

 Posts: 35

RE: Stroke example for CCLabelTTF and CCSprite. 10 months ago

I suspect the latest line should be read as

addChild(tex, sprite->getZOrder() - 1);

Thanks for sharing this.

Alexandr Gerasimov

 Posts: 8

RE: Stroke example for CCLabelTTF and CCSprite. 10 months ago

Alexander Belchenko wrote:

I suspect the latest line should be read as

addChild(tex, sprite->getZOrder() - 1);

Thanks for sharing this.

Exactly! Thx and welcome!

xavi pinol

 Posts: 9

RE: Stroke example for CCLabelTTF and CCSprite. 9 months ago

It actually works on iOS, but I'm having some problems on Android.

I know is sounds weird, but have a look at the screenshots

Android:

iOS:

Is there any solution for this?

xavi pinol

 Posts: 9

RE: Stroke example for CCLabelTTF and CCSprite. 9 months ago

Solved with:

rt->getSprite()->getTexture()->setAntiAliasTexParameters();

xavi pinol wrote:

It actually works on iOS, but I'm having some problems on Android.

I know is sounds weird, but have a look at the screenshots
...

Alexandr Gerasimov

 Posts: 8

RE: Stroke example for CCLabelTTF and CCSprite. 9 months ago

Right, thx for solving! I use setAntiAliasTexParameters by default for all my textures 

xavi pinol wrote:

Solved with:

rt->getSprite()->getTexture()->setAntiAliasTexParameters();

xavi pinol wrote:

It actually works on iOS, but I'm having some problems on Android.

I know is sounds weird, but have a look at the screenshots
...

Lance Gray

 Posts: 468

 Location: Coffee World

RE: Stroke example for CCLabelTTF and CCSprite. 9 months ago

Thanks for sharing!

Check out my blog: sudo make_me_a_game

GVBox Production

 Posts: 19

RE: Stroke example for CCLabelTTF and CCSprite. 6 months ago

Thanks for sharing !

juyoung kim

 Posts: 8

RE: Stroke example for CCLabelTTF and CCSprite. 5 months ago

Thanks for sharing!

Austin K

 Posts: 3

RE: Stroke example for CCLabelTTF and CCSprite. 5 months ago

Thank you for sharing this! Has anyone created HTML5 support? I could really use it.

Thanks.

Simon Pan

 Posts: 66

 Location: Taiwan

RE: Stroke example for CCLabelTTF and CCSprite. 4 months ago

Alexandr Gerasimov wrote:

Hey guys! Several days ago i found a cocs2d-iphone examples "stroke effect for CCLabelTTF objects". Here is the link to the cocos2d-iphone forum: http://www.cocos2d-iphone.org/forum/topic/12126

I made little modifications in this example and rewrote it for c++. Here is my code:

[...]
I added "opacity" property and possibility to add Stroke for all CCSprite nodes.

Example of usage:
[...]

 

Add the check while CCSprite is using setAnchorPoint as below:

static CCRenderTexture* createStroke(CCSprite* label, int size, ccColor3B color, GLubyte opacity){

        CCRenderTexture* rt = CCRenderTexture::create(label->getTexture()->getContentSize().width + size * 2,

                                                      label->getTexture()->getContentSize().height+size * 2);

        CCPoint originalPos = label->getPosition();

        ccColor3B originalColor = label->getColor();

        GLubyte originalOpacity = label->getOpacity();

        label->setColor(color);

        label->setOpacity(opacity);

        bool originalVisibility = label->isVisible();

        ccBlendFunc originalBlend = label->getBlendFunc();

        ccBlendFunc bf = {GL_SRC_ALPHA, GL_ONE};

        label->setBlendFunc(bf);

        CCPoint bottomLeft = ccp(

                                 label->getTexture()->getContentSize().width * label->getAnchorPoint().x + size,

                                 label->getTexture()->getContentSize().height * label->getAnchorPoint().y + size);

        //原來沒有判斷AnchorPoint的寫法

        //  CCPoint positionOffset= ccp(   - label->getTexture()->getContentSize().width / 2,

        //                                  - label->getTexture()->getContentSize().height / 2);

        //SetAnchorPoint會影響到positionOffset,所以要做判斷

        CCPoint positionOffset = CCPointZero;

        if(label->getAnchorPoint().x == 0.5f){

            positionOffset.x = 0;

        }else if(label->getAnchorPoint().x == 0.0f){

            positionOffset.x =- label->getTexture()->getContentSize().width / 2;

        }else{

            positionOffset.x = label->getTexture()->getContentSize().width/2;

        }

        if(label->getAnchorPoint().y == 0.5f){

            positionOffset.y = 0;

        }else if(label->getAnchorPoint().y == 0.0f){

            positionOffset.y =- label->getTexture()->getContentSize().height / 2;

        }else{

            positionOffset.y =  label->getTexture()->getContentSize().height/2;

        }

        CCPoint position = ccpSub(originalPos, positionOffset);

        rt->begin();

        for (int i=0; i<360 data-blogger-escaped-for="" data-blogger-escaped-i="" data-blogger-escaped-label-="" data-blogger-escaped-needs="" data-blogger-escaped-optimize="" data-blogger-escaped-should="" data-blogger-escaped-that="" data-blogger-escaped-you="" data-blogger-escaped-your="">setPosition(

                               ccp(bottomLeft.x + sin(CC_DEGREES_TO_RADIANS(i))*size, bottomLeft.y + cos(CC_DEGREES_TO_RADIANS(i))*size)

                               );

            label->visit();

        }

        rt->end();

        label->setPosition(originalPos);

        label->setColor(originalColor);

        label->setBlendFunc(originalBlend);

        label->setVisible(originalVisibility);

        label->setOpacity(originalOpacity);

        rt->setPosition(position);

        //反踞齒

        rt->getSprite()->getTexture()->setAntiAliasTexParameters();

        return rt;

    }

 

Dony Karlos

 Posts: 13

 Location: FBoooW

RE: Stroke example for CCLabelTTF and CCSprite. 16 days ago

is there lua code of this?

 :::::::::::::::::::::::

From: http://www.cocos2d-x.org/forums/6/topics/22335

原文地址:https://www.cnblogs.com/wishing/p/3450104.html