分析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组件无效的原因

1. 修改C++层相关代码

1.找到 CanvasRenderingContext2D类并进行简单的修改(文件目录在 cocos/platform/CCCanvasRenderingContext2D.h)。添加上面分析出来的变量。

//
class CC_DLL CanvasRenderingContext2D {
    // TODO lxx 阴影 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