分析LabelShadow组件无效的原因
LabelShadow组件在原生平台无效,原因是LabelShadow组件只在Web平台上实现了该功能,在原生平台上没有实现该功能。
简单分析一下源码(文件:engine/cocos2d/core/render/utils/label/ttf.js)。游戏引擎是如何使用LabelShadow组件进行描边的。
通关观察ttf.js源码中 _updateTexture 和 _setupShadow两个函数。分析出描边所需要的四个参数:
- shadowColor: 描边的样式(RGBA)
- shadowBlur: 描边模糊的宽度
- shadowOffsetX: 描边的X轴的偏移量
- shadowOffsetY:描边的Y轴的偏移量
_updateTexture() {
......
......
// only one set shadow and outline
if (_shadowComp) {
this._setupShadow();
}
......
......
}
_setupShadow () {
_context.shadowColor = `rgba(${_shadowColor.r}, ${_shadowColor.g}, ${_shadowColor.b}, ${_shadowColor.a / 255})`;
_context.shadowBlur = _shadowComp.blur;
_context.shadowOffsetX = _shadowComp.offset.x;
_context.shadowOffsetY = -_shadowComp.offset.y;
}
如何解决LabelShadow组件在原生平台(Android)无效
1. 修改C++层相关代码
1.找到 CanvasRenderingContext2D类并进行简单的修改(文件目录在 cocos/platform/CCCanvasRenderingContext2D.h)。添加上面分析出来的变量。
//
class CC_DLL CanvasRenderingContext2D {
// TODO 虣虣 阴影 begin
void set_shadowColor(const std::string& shadowColor);
void set_shadowBlur(float shadowBlur);
void set_shadowOffsetX(float shadowOffsetX);
void set_shadowOffsetY(float shadowOffsetY);
// TODO 虣虣 阴影 end
// TODO 虣虣 阴影 begin
std::string _shadowColor = "#000";
float _shadowBlur = 1.0f;
float _shadowOffsetX = 1.0f;
float _shadowOffsetY = 1.0f;
// TODO 虣虣 阴影 end
}
2.在相关android平台下修改这些变量的读写属性,以及调用Java层代码,文件所在目录(cocos/platform/android/CCCanvasRenderingContext2D-android.cpp)
// TODO 虣虣 阴影 begin
void setShadowColor(float r, float g, float b, float a)
{
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setShadowColor", r, g, b, a);
}
void setShadowBlur(float shadowBlur)
{
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setShadowBlur", shadowBlur);
}
void setShadowOffsetX(float shadowOffsetX)
{
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setShadowOffsetX", shadowOffsetX);
}
void setShadowOffsetY(float shadowOffsetY)
{
JniHelper::callObjectVoidMethod(_obj, JCLS_CANVASIMPL, "setShadowOffsetY", shadowOffsetY);
}
// TODO 虣虣 阴影 end
// TODO 虣虣 阴影 begin
void CanvasRenderingContext2D::set_shadowColor(const std::string& shadowColor) {
CSSColorParser::Color color = CSSColorParser::parse(shadowColor);
_impl->setShadowColor(color.r/255.0f, color.g/255.0f, color.b/255.0f, color.a);
}
void CanvasRenderingContext2D::set_shadowBlur(float shadowBlur) {
_impl->setShadowBlur(shadowBlur);
}
void CanvasRenderingContext2D::set_shadowOffsetX(float shadowOffsetX) {
_impl->setShadowOffsetX(shadowOffsetX);
}
void CanvasRenderingContext2D::set_shadowOffsetY(float shadowOffsetY) {
_impl->setShadowOffsetX(shadowOffsetY);
}
// TODO 虣虣 阴影 end
2. 修改JAVA层相关代码
修改 cocos/platform/android/java/src/org/cocos2dx/lib/CanvasRenderingContext2DImpl.java 文件,修改如下
// cocos/platform/android/java/src/org/cocos2dx/lib/CanvasRenderingContext2DImpl.java
public class CanvasRenderingContext2DImpl {
// TODO 虣虣 阴影 begin
private int mShadowStyleR = 0;
private int mShadowStyleG = 0;
private int mShadowStyleB = 0;
private int mShadowStyleA = 0;
private float mShadowBlur = 0;
private float mShadowOffsetX = 0;
private float mShadowOffsetY = 0;
// TODO 虣虣 阴影 end
// TODO 虣虣 阴影 begin
// 设置阴影颜色
private void setShadowColor(float r, float g, float b, float a) {
// Log.d(TAG, "setShadowStyle: " + r + ", " + g + ", " + b + ", " + a);
mShadowStyleR = (int)(r * 255.0f);
mShadowStyleG = (int)(g * 255.0f);
mShadowStyleB = (int)(b * 255.0f);
mShadowStyleA = (int)(a * 255.0f);
}
// 设置描边宽度
private void setShadowBlur(float shadowBlur) {
mShadowBlur = shadowBlur;
}
// 设置描边的偏移X
private void setShadowOffsetX(float shadowOffsetX) {
mShadowOffsetX = shadowOffsetX;
}
// 设置描边的偏移Y
private void setShadowOffsetY(float shadowOffsetY) {
mShadowOffsetY = shadowOffsetY;
}
// TODO 虣虣 阴影 end
private void fillText(String text, float x, float y, float maxWidth) {
// Log.d(TAG, "this: " + this + ", fillText: " + text + ", " + x + ", " + y + ", " + ", " + maxWidth);
createTextPaintIfNeeded();
mTextPaint.setARGB(mFillStyleA, mFillStyleR, mFillStyleG, mFillStyleB);
mTextPaint.setStyle(Paint.Style.FILL);
// TODO 虣虣 阴影 begin
int color = Color.argb(mShadowStyleA, mShadowStyleR, mShadowStyleG, mShadowStyleB);
mTextPaint.setShadowLayer(mShadowBlur, mShadowOffsetX, mShadowOffsetX, color);
// TODO 虣虣 阴影 end
scaleX(mTextPaint, text, maxWidth);
Point pt = convertDrawPoint(new Point(x, y), text);
mCanvas.drawText(text, pt.x, pt.y, mTextPaint);
}
}
3. 注册相关属性给JS层调用
此处为了方便些文章,我是手动写到文件里面的(相关文件 cocos/scripting/jsb-bindings/manual/jsb-cocos2dx-manual.cpp),这里可以使用自动绑定相关功能。
// TODO 虣虣 阴影 begin
BIND_PROP_WITH_TYPE__CONV_FUNC__RETURN(CanvasRenderingContext2D, shadowColor, std::string, seval_to_std_string, setString)
BIND_PROP_WITH_TYPE__CONV_FUNC__RETURN(CanvasRenderingContext2D, shadowBlur, float, seval_to_float, setFloat)
BIND_PROP_WITH_TYPE__CONV_FUNC__RETURN(CanvasRenderingContext2D, shadowOffsetX, float, seval_to_float, setFloat)
BIND_PROP_WITH_TYPE__CONV_FUNC__RETURN(CanvasRenderingContext2D, shadowOffsetY, float, seval_to_float, setFloat)
// TODO 虣虣 阴影 end
// TODO 虣虣 阴影 begin
_SE_DEFINE_PROP(CanvasRenderingContext2D, shadowColor)
_SE_DEFINE_PROP(CanvasRenderingContext2D, shadowBlur)
_SE_DEFINE_PROP(CanvasRenderingContext2D, shadowOffsetX)
_SE_DEFINE_PROP(CanvasRenderingContext2D, shadowOffsetY)
// TODO 虣虣 阴影 end
如何解决LabelShadow组件在原生平台(IOS)无效
前面已经修改过C++部分的代码,这里不再过多的叙说,简单的说一下IOS需要修改的内容。IOS需要修改的文件在 cocos/platform/apple/CCCanvasRenderingContext2D-apple.mm文件中。
- 设置相关字体阴影属性
// CCCanvasRenderingContext2D-apple.mm
@interface CanvasRenderingContext2DImpl : NSObject {
....
// TODO 虣虣 begin 文字阴影
// 阴影颜色
cocos2d::Color4F _shadowStyle;
// 阴影模糊的宽度
float _shadowBlur;
// 阴影X偏移量
float _shadowOffsetX;
// 阴影Y偏移量
float _shadowOffsetY;
// TODO 虣虣 end
....
}
....
@property (nonatomic, assign) float shadowBlur;
@property (nonatomic, assign) float shadowOffsetX;
@property (nonatomic, assign) float shadowOffsetY;
@synthesize shadowBlur = _shadowBlur;
@synthesize shadowOffsetX = _shadowOffsetX;
@synthesize shadowOffsetY = _shadowOffsetY;
....
- 设置相关字体阴影的属性,共JS层调用
// CCCanvasRenderingContext2D-apple.mm
// TODO 虣虣 begin 设置相关属性,共JS调用。
// 设置字体阴影相关属性(颜色,粗细,偏移)
-(void) setShadowStyleWithRed:(CGFloat) r green:(CGFloat) g blue:(CGFloat) b
alpha:(CGFloat) a {
_shadowStyle.r = r;
_shadowStyle.g = g;
_shadowStyle.b = b;
_shadowStyle.a = a;
}
void CanvasRenderingContext2D::set_shadowColor(const std::string &shadowColor) {
CSSColorParser::Color color = CSSColorParser::parse(shadowColor);
[_impl setShadowStyleWithRed:color.r/255.0f green:color.g/255.0f blue:color.b/255.0f alpha:color.a];
}
void CanvasRenderingContext2D::set_shadowBlur(float shadowBlur) {
_shadowBlur = shadowBlur;
_impl.shadowBlur = _shadowBlur;
}
void CanvasRenderingContext2D::set_shadowOffsetX(float shadowOffsetX) {
_shadowOffsetX = shadowOffsetX;
_impl.shadowOffsetX = shadowOffsetX;
}
void CanvasRenderingContext2D::set_shadowOffsetY(float shadowOffsetY) {
_shadowOffsetY = shadowOffsetY;
_impl.shadowOffsetY = _shadowOffsetY;
}
// TODO 虣虣 end
- 在fillText函数增加相关代码
-(void) fillText:(NSString*) text x:(CGFloat) x y:(CGFloat) y maxWidth:(CGFloat) maxWidth {
....
// text color
CGContextSetRGBFillColor(_context, _fillStyle.r, _fillStyle.g, _fillStyle.b, _fillStyle.a);
CGContextSetShouldSubpixelQuantizeFonts(_context, false);
CGContextBeginTransparencyLayerWithRect(_context, CGRectMake(0, 0, _width, _height), nullptr);
CGContextSetTextDrawingMode(_context, kCGTextFill);
// TODO 虣虣 begin
NSColor* color = [NSColor colorWithRed:_shadowStyle.r green:_shadowStyle.g blue:_shadowStyle.b alpha:_shadowStyle.a];
CGContextSetShadowWithColor(_context, CGSizeMake(_shadowOffsetX, _shadowOffsetY), _shadowBlur, color.CGColor);
// TODO 虣虣 end
....
CGContextEndTransparencyLayer(_context);
[self restoreContext];
}
说明: Android平台已经测试过,IOS平台相关代码没有经过测试
如果你对所分享的内容感兴趣,可以关注微信公众号【游戏讲坛】。
游戏讲坛已开通微信公众号交流群。如想加入请关注微信公众号。