【问题标题】:Is there really no way to style SKLabelNode?真的没有办法给 SKLabelNode 设置样式吗?
【发布时间】:2015-03-07 06:27:29
【问题描述】:

真的没有办法给 SKLabelNode 设置样式吗?我的意思是改变字体和颜色。我知道我可以通过在第一个 SKLabelNode 后面创建第二个 SKLabelNode 来添加阴影之类的操作(已经很老套了)。由于显而易见的原因,为我的字体创建图像也很糟糕。似乎很奇怪,您无法摆脱无聊的扁平文本。

我的意思是..即使 spritekit 节点数也有很酷的渐变样式...这是怎么做到的?!

好的,所以我在这里尝试重新创建渐变效果。我已经尝试了混合模式的每一种组合,以及颜色和 colorBlendFactor 的多种组合。

阿尔法

相乘

添加

这里是代码

let testNode = SKLabelNode(text: "hey there")
testNode.fontSize = 30
testNode.color = SKColor.blueColor()
testNode.colorBlendFactor = 1
testNode.fontName = "Helvetica-Bold"
testNode.blendMode = SKBlendMode.Multiply
testNode.colorBlendFactor = 0.6
testNode.position = CGPoint(x: self.size.width/2, y: self.size.height/2)

self.addChild(testNode)

【问题讨论】:

  • fontColorcolorcolorBlendFactor 的正确值怎么样? blendMode 也可以提供帮助。
  • 我想我的问题是,你能不能用 spritekit 重新创建我上图中的 nodecount 字体?
  • 试试我刚才的建议。看看你得到了什么。
  • 试试看你会得到什么。
  • 那个文本实际上是一个位图字体纹理。苹果为此提供了一个尚未引入的私人课程。请参阅对此问题的评论:stackoverflow.com/q/18954144/2158465

标签: ios objective-c swift sprite-kit sklabelnode


【解决方案1】:

经过大量的试验和错误,我得到了这个工作:

{
        const CGFloat LABELFONTSIZE = 100;
        SKColor* fontcolor = [SKColor redColor];

        UIFont* font = [AppDelegate fontOfType:Fonttype_main size:LABELFONTSIZE]; // LABELFONTSIZE not used here but whatever.
        SKLabelNode* label = [SKLabelNode labelNodeWithFontNamed:font.fontName];
        label.fontColor = fontcolor;
        label.verticalAlignmentMode = SKLabelVerticalAlignmentModeTop;
        self.labelScore = label;
        //label.zPosition = Z_HUD;
        label.fontSize = LABELFONTSIZE;

        self.score = 0;

        const CGPoint LABELPOSITION = CGPointMake(self.size.width * 0.5, self.size.height);
        label.position = LABELPOSITION;

#define USESHADER
#ifdef USESHADER
        SKShader* myShader = [SKShader shaderWithFileNamed:@"TheShader"];
        NSAssert(myShader, @"myShader was nil!");

        SKEffectNode* effectNode = [SKEffectNode node];
        effectNode.zPosition = Z_HUD;
        effectNode.shader = myShader;
        effectNode.shouldEnableEffects = YES;
        [self addChild:effectNode];

        [effectNode addChild:label];
#else
        label.zPosition = Z_HUD;
        [self addChild:label];
#endif

        [label runAction:[SKAction repeatActionForever:[SKAction sequence:@[
                                                                            [SKAction moveByX:0 y:-300 duration:3.0],
                                                                            [SKAction moveByX:0 y:300 duration:3.0],
                                                                            ]]]];
    }

TheShader.fsh:

void main()
{
    float gradient = v_tex_coord.y;
    //vec4 color = SKDefaultShading(); // the current label color THIS DOES NOT WORK ON IOS 9.2 AND EARLIERISH (MAYBE IT DOES ON IOS 8) WORKS ONLY ON IOS 9.3 BETA AT THIS MOMENT!
    vec4 color = texture2D(u_texture, v_tex_coord);
    color = vec4(color.r + gradient, color.g + gradient, color.b + gradient, color.a);
    color.rgb *= color.a; // set background to alpha 0
    gl_FragColor = color;
}

它基于 Loengard 的回答,但不使用任何制服。着色器中的一些内容在许多 iOS 9 版本上有效/无效,包括截至目前的最新 iOS 9.3 beta (20160115)。 上面的代码运行良好,它甚至不关心标签在屏幕上的位置;我上下动画标签以确认这一点。

【讨论】:

    【解决方案2】:

    使用着色器非常简单。在项目中添加一个名为“TheShader.fsh”的文本文件:

    void main()
    {
        float yPos = gl_FragCoord.y - labelBase;
        float gradient = yPos / u_sprite_size.y; // ranges from 0 at base to 1 at top
    
        vec4 color = SKDefaultShading(); // the current label color
        color = vec4(gradient + color.r, gradient + color.g, gradient + color.b, color.a);
        color.rgb *= color.a; // set background to alpha 0
    
        gl_FragColor = color;
    }
    

    现在在 SKScene 中创建一个 SKEffectNode,将其着色器设置为“TheShader”,并将您的标签添加为效果节点的子节点。标签将使用垂直渐变绘制,范围从底部的标签 fontColor 到顶部的白色。

    override func didMoveToView(view: SKView)
    {
        makeGradientLabel("318 nodes 60.0 fps", labelPosition: CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame)))
    }
    
    func makeGradientLabel(labelText: String, labelPosition: CGPoint)
    {
        let myShader = SKShader(fileNamed: "TheShader")
        let labelBase = SKUniform(name: "labelBase", float: Float(labelPosition.y))
        myShader.addUniform(labelBase)
    
        let effectNode = SKEffectNode()
        effectNode.shader = myShader
        effectNode.shouldEnableEffects = true
        addChild(effectNode)
    
        let theLabel = SKLabelNode(fontNamed: "Courier")
        theLabel.fontSize = 36
        theLabel.fontColor = SKColor.blueColor()
        theLabel.text = labelText
        theLabel.position = labelPosition
    
        effectNode.addChild(theLabel)
    }
    

    如果您移动标签,您需要更新 labelBase 统一,以便着色器知道它在哪里:

    labelBase.floatValue = Float(theLabel.position.y)
    

    【讨论】:

    • 我试过了,但标签对我来说只是蓝色的。我确实为 ObjC 重写了它,但希望没有犯任何错误。
    • 我在控制台中收到一条错误消息:错误:使用未声明的标识符“SKDefaultShading”
    • Oups 有一个关于这件事的相关主题:stackoverflow.com/questions/31492404/…
    【解决方案3】:

    SKLabelNode 没有任何方法或属性可以让您实现渐变样式。正如 cmets 中的链接所述,SpriteKit 确实有一个 SKBitmapFont 私有类,但这对您没有帮助。

    您可以推出自己的解决方案或尝试字形设计器:https://71squared.com/glyphdesigner

    【讨论】:

      猜你喜欢
      • 2016-02-12
      • 1970-01-01
      • 2021-05-18
      • 1970-01-01
      • 2022-06-29
      • 2012-05-28
      • 2011-02-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多