[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
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)
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.
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!
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?
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
...
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
...
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
Posts: 19
RE: Stroke example for CCLabelTTF and CCSprite. 6 months ago
Thanks for sharing !
Posts: 8
RE: Stroke example for CCLabelTTF and CCSprite. 5 months ago
Thanks for sharing!
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.
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;
}
Posts: 13
Location: FBoooW
RE: Stroke example for CCLabelTTF and CCSprite. 16 days ago
is there lua code of this?
:::::::::::::::::::::::