Jonny
Jonny

Reputation: 16308

colorizeWithColor and SKLabelNode

The SKAction colorizeWithColor: does as per the docs only work with SKSpriteNode, so what do we do with SKLabelNode? SKLabelNode does have both color and colorBlendFactor properties that can be set statically. Is there some way to animate this with SKAction?

My current approach is to render a SKLabelNode to a texture using SKView's instance method textureFromNode, but just get nil texture out of that atm :-(

Update: What do you know. I think I found out the problem with the texture rendering. It's not possible to redner a texture in the init method of SKScene, because self.view is nil at that point. So I tried it in didMoveToView and voila, texture rendered. Thanks anyway :-)

Upvotes: 2

Views: 4261

Answers (4)

GuessGen
GuessGen

Reputation: 185

Maybe somebody will find this useful.

   func changeColorForLabelNode(labelNode: SKLabelNode, toColor: SKColor, withDuration: NSTimeInterval) {
    labelNode.runAction(SKAction.customActionWithDuration(withDuration, actionBlock: {
      node, elapsedTime in

      let label = node as SKLabelNode

      let toColorComponents = CGColorGetComponents(toColor.CGColor)
      let fromColorComponents = CGColorGetComponents(label.fontColor.CGColor)

      let finalRed = fromColorComponents[0] + (toColorComponents[0] - fromColorComponents[0])*CGFloat(elapsedTime / CGFloat(withDuration))
      let finalGreen = fromColorComponents[1] + (toColorComponents[1] - fromColorComponents[1])*CGFloat(elapsedTime / CGFloat(withDuration))
      let finalBlue = fromColorComponents[2] + (toColorComponents[2] - fromColorComponents[2])*CGFloat(elapsedTime / CGFloat(withDuration))
      let finalAlpha = fromColorComponents[3] + (toColorComponents[3] - fromColorComponents[3])*CGFloat(elapsedTime / CGFloat(withDuration))

      labelNode.fontColor = SKColor(red: finalRed, green: finalGreen, blue: finalBlue, alpha: finalAlpha)
    }))
  }

You can even check the result of this function in use in this demo: https://www.youtube.com/watch?v=ZIz8Bn0-hUA&feature=youtu.be

I decided to write here a short nice solution, but if you need more details, check this question: SKAction.colorizeWithColor makes SKLabelNode disappear

Upvotes: 4

Hugh
Hugh

Reputation: 443

SKLabelNode also has a fontColor property that you can set. However, it does not respond to the colorizeWithColor method.

Yet, you can still get it to dynamically change the color of the text by syncing it with another SKSpriteNode color. If you call colorizeWithColor on your sprite, the font color changes with it. And that includes color transitions over the specified duration. Example:

    [_tileCountLabel runAction:[SKAction repeatActionForever:
                            [SKAction customActionWithDuration:COLOR_TRANSITION_SPEED actionBlock:^(SKNode *node, CGFloat elapsedTime) {
    _tileCountLabel.fontColor = _tileLayer0.color;
}]]];

Also, I tried using SKCropNode mask to try setting the font color through a parent SKSpriteNode. The colorizeWithColor method on the SKSpriteNode worked, but the font was badly mangled and chunky. So, not useful.

Upvotes: 3

AaronBaker
AaronBaker

Reputation: 1033

If you want to colorize an SKLabelNode, you could try using the label as a mask and colorizing the background:

SKSpriteNode *background = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:CGSizeMake(200.0, 200.0)];
SKAction *turnRed = [SKAction colorizeWithColor:[UIColor redColor] colorBlendFactor:1.0 duration:2.0];

SKCropNode *cropNode = [SKCropNode node];
cropNode.maskNode = [yourAwesomeLabel copy];
[cropNode addChild:background];

[background runAction:turnRed];

[self addChild:cropNode];

Upvotes: 2

Jonny
Jonny

Reputation: 16308

So here is the SKTexture/SKSpriteNode workaround solution. It could maybe be wrapped in its own class for ease of use. And the one thing to remember is to render this where self.view is not nil...

SKLabelNode *labNode = [SKLabelNode labelNodeWithFontNamed:FONT_GAME];
labNode.fontSize = 30.0f;
labNode.fontColor = [SKColor whiteColor];
labNode.text = @"TEST";

SKTexture *texture;

NSAssert(self.view != nil, @"Can't access self.view so sorry.");
texture = [self.view textureFromNode:labNode];
DLog(@"texture: %@", texture);
if (texture != nil) {
    texture.filteringMode = SKTextureFilteringNearest;

    SKSpriteNode *spriteText = [SKSpriteNode spriteNodeWithTexture:texture];
    DLog(@"spriteText.size: %@", NSStringFromSize(spriteText.size));
    spriteText.anchorPoint = ccp(0, 0.5);
    spriteText.position = ccp(0, 25);

    [self addChild:spriteText];

    [spriteText runAction:[SKAction repeatActionForever:[SKAction sequence:@[
                                                                             [SKAction colorizeWithColor:SKColor.yellowColor colorBlendFactor:1 duration:1],
                                                                             [SKAction colorizeWithColor:SKColor.yellowColor colorBlendFactor:0 duration:1],
                                                                             ]]]];
}
else {
    DLog(@"Texture is nil!");
}

Upvotes: 2

Related Questions