I'm working on a game with SpriteKit. I'm drawing a shape with SKShapeNode. Now I want to animate its colour change but the SKActions is not working for SKShapeNode. Is there any way to do this or I have to use a different approach?
Thank you.
EDIT:
Thanks to LearnCocos2D I was able to come up with this quick (and totally not perfect) solution.
int groundChangeInterval = 5; SKColor *originalColor = [SKColor colorWithRed:0.92 green:0.87 blue:0.38 alpha:1.0]; SKColor *finalColor = [SKColor colorWithRed:0.29 green:0.89 blue:0.31 alpha:1.0]; CGFloat red1 = 0.0, green1 = 0.0, blue1 = 0.0, alpha1 = 0.0; [originalColor getRed:&red1 green:&green1 blue:&blue1 alpha:&alpha1]; CGFloat red2 = 0.0, green2 = 0.0, blue2 = 0.0, alpha2 = 0.0; [finalColor getRed:&red2 green:&green2 blue:&blue2 alpha:&alpha2]; SKAction *changeGroundColor = [SKAction customActionWithDuration:groundChangeInterval actionBlock:^(SKNode *node, CGFloat elapsedTime) { CGFloat step = elapsedTime/groundChangeInterval; CGFloat red3 = 0.0, green3 = 0.0, blue3 = 0.0; red3 = red1-(red1-red2)*step; green3 = green1-(green1-green2)*step; blue3 = blue1-(blue1-blue2)*step; [(SKShapeNode*)node setFillColor:[SKColor colorWithRed:red3 green:green3 blue:blue3 alpha:1.0]]; [(SKShapeNode*)node setStrokeColor:[SKColor colorWithRed:red3 green:green3 blue:blue3 alpha:1.0]]; }];
I only needed to fade two specific colours so it is not a universal solution but it is enough for now.
Thanks
Updated for Swift 4.2
This the common code that you need to place in and extension file or something of the sort.
func lerp(a : CGFloat, b : CGFloat, fraction : CGFloat) -> CGFloat { return (b-a) * fraction + a } struct ColorComponents { var red = CGFloat(0) var green = CGFloat(0) var blue = CGFloat(0) var alpha = CGFloat(0) } extension UIColor { func toComponents() -> ColorComponents { var components = ColorComponents() getRed(&components.red, green: &components.green, blue: &components.blue, alpha: &components.alpha) return components } } extension SKAction { static func colorTransitionAction(fromColor : UIColor, toColor : UIColor, duration : Double = 0.4) -> SKAction { return SKAction.customAction(withDuration: duration, actionBlock: { (node : SKNode!, elapsedTime : CGFloat) -> Void in let fraction = CGFloat(elapsedTime / CGFloat(duration)) let startColorComponents = fromColor.toComponents() let endColorComponents = toColor.toComponents() let transColor = UIColor(red: lerp(a: startColorComponents.red, b: endColorComponents.red, fraction: fraction), green: lerp(a: startColorComponents.green, b: endColorComponents.green, fraction: fraction), blue: lerp(a: startColorComponents.blue, b: endColorComponents.blue, fraction: fraction), alpha: lerp(a: startColorComponents.alpha, b: endColorComponents.alpha, fraction: fraction)) (node as? SKSpriteNode)?.color = transColor } ) } }
Usage:
redSKSpriteNodeThatBecomesBlue.run(SKAction.colorTransitionAction(fromColor: .red, toColor: .blue, duration: 5))
Please note that for SKShapeNode or other purposes you need to rewrite this line to suit your need:
(node as? SKSpriteNode)?.color = transColor
This solution is heavily inspired originally by Paddy Collins answer.
Use customActionWithDuration:block:
and change the fillColor
or strokeColor
properties.
I suppose the colorize actions won't work because SKShapeNode has no color
property. It's worth a try to add this property to the class in a subclass or category and redirect it to fillColor
or strokeColor
or both.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With