SKShapeNode - 动画颜色变化

ada*_*dam 21 objective-c ios sprite-kit

我正在使用SpriteKit进行游戏.我正在使用SKShapeNode绘制一个形状.现在我想设置其颜色变化的动画,但SKActions不适用于SKShapeNode.有没有办法做到这一点,或者我必须使用不同的方法?

谢谢.

编辑:

感谢LearnCocos2D,我能够提出这个快速(并且完全不完美)的解决方案.

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]];
}];
Run Code Online (Sandbox Code Playgroud)

我只需要淡化两种特定的颜色,因此它不是一种通用的解决方案,但现在已足够了.

谢谢

GOR*_*GOR 27

针对Swift 4.2进行了更新

这是您需要放入的公共代码和扩展文件或类似的东西.

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
        }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

redSKSpriteNodeThatBecomesBlue.run(SKAction.colorTransitionAction(fromColor: .red, toColor: .blue, duration: 5))

请注意,对于SKShapeNode或其他目的,您需要重写此行以满足您的需要:

(node as? SKSpriteNode)?.color = transColor

这个解决方案最初是由Paddy Collins回答的.


Lea*_*s2D 16

使用customActionWithDuration:block:和更改fillColorstrokeColor属性.

我认为着色操作不起作用,因为SKShapeNode没有color属性.值得尝试将此属性添加到子类或类别中的类,并将其重定向到fillColorstrokeColor或两者.

  • 此解决方案不会为颜色变化设置动画,它只会立即发生. (2认同)

Pat*_*ins 8

这是我的实施.我觉得更容易阅读.

-(SKAction*)getColorFadeActionFrom:(SKColor*)col1 toColor:(SKColor*)col2 {

    // get the Color components of col1 and col2
    CGFloat r1 = 0.0, g1 = 0.0, b1 = 0.0, a1 =0.0;
    CGFloat r2 = 0.0, g2 = 0.0, b2 = 0.0, a2 =0.0;
    [col1 getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
    [col2 getRed:&r2 green:&g2 blue:&b2 alpha:&a2];

    // return a color fading on the fill color
    CGFloat timeToRun = 0.3;

    return [SKAction customActionWithDuration:timeToRun actionBlock:^(SKNode *node, CGFloat elapsedTime) {

        CGFloat fraction = elapsedTime / timeToRun;

        SKColor *col3 = [SKColor colorWithRed:lerp(r1,r2,fraction)
                                        green:lerp(g1,g2,fraction)
                                         blue:lerp(b1,b2,fraction)
                                        alpha:lerp(a1,a2,fraction)];

        [(SKShapeNode*)node setFillColor:col3];
        [(SKShapeNode*)node setStrokeColor:col3];
    }];
}

double lerp(double a, double b, double fraction) {
    return (b-a)*fraction + a;
}
Run Code Online (Sandbox Code Playgroud)