1
votes

I'm trying to making a sprite flash white, like when it takes on damage. This would involve controlling some parameter via an SKAction. First I tried using an SKCropNode in conjunction with a white SKShapeNode, but I don't think I completely understand how that works because it didn't do anything. My second attempt was to colorize the sprite, but I've found out that when you colorize a sprite white, it just shows its original colours. I'm sure a shader would work, but I don't have much experience with them. Any ideas?

[EDIT]

Ok, after reading a million more websites on the this topic, I came across the following SO question, which said that SKCropNodes only work with SKSpriteNodes (for masking, etc). So I've updated my code and allows my sprite to turn white. I thought I'd be able to run an SKAction to turn down the alpha on the white SKSpriteNode to reveal the masking node, but that just makes the entire sprite disappear. So then I thought maybe I can add the original image to the SKCropNode, but then the white SKSpriteNode goes away. I decided to create an SKAction to dim the white SKSpriteNode and then add the original node to the SKCropNode. It works, but is there a better way?

SKSpriteNode *prod = [SKSpriteNode spriteNodeWithImageNamed:@"some image"];
[prod setSize:CGSizeMake(prod.frame.size.width*0.2, prod.frame.size.height*0.2)];
prod.zPosition = -1;

SKSpriteNode *mask = [SKSpriteNode spriteNodeWithImageNamed:@"some image"];
[mask setSize:CGSizeMake(mask.frame.size.width*0.2, mask.frame.size.height*0.2)];
mask.zPosition = 1;
//mask.position = CGPointMake(300, 300);

SKSpriteNode *shape = [SKSpriteNode spriteNodeWithColor:[NSColor whiteColor] size:CGSizeMake(800, 600)];
shape.zPosition = 2;

SKCropNode *cropNode = [SKCropNode node];
cropNode.maskNode = mask;

[cropNode addChild:shape];
//[cropNode addChild:prod];
cropNode.position = CGPointMake(300, 300);
[self addChild:cropNode];

SKAction *fadeOut = [SKAction fadeAlphaTo:0 duration:0.1];
[shape runAction:fadeOut completion:^{
    [cropNode addChild:prod];
}];
1
Colorize with color action wont help here due to fact how blending works : stackoverflow.com/q/20715177/3402095 Try to make a hit-state image (completely white image). That would be the easiest solution. Then just swap textures, back and forth after certain delay. Or if you need animation, use two sprites and fade in/out hit-state texture quickly...Whirlwind
Is there a way to do this with an SKCropNode? That would be ideal so that I don't have to have two different versions of each sprite.02fentym
Can't say off-hand what would be a performant or elegant solution, but it is probably doable. If you update your question with what you have tried so far, probably somebody will be able to help...Whirlwind
I understand. I added some code up top and an image of what that code generates...not exactly what I'm looking for.02fentym

1 Answers

2
votes

I figured it out. Here's the important part of the class I wrote to handle this...ignore the name of the class...it's something specific to my app, just call it whatever you need it to be called:

VersusImage.h

#import <SpriteKit/SpriteKit.h>

@interface VersusImage : SKSpriteNode


-(instancetype) initWithImage:(SKSpriteNode*)image;
-(void) flashWhite;

@end

VersusImage.m

#import "VersusImage.h"

@interface VersusImage()

@property SKCropNode *cropNode;
@property SKSpriteNode *image;
@property SKSpriteNode *shape;

@end

@implementation VersusImage

-(instancetype) initWithImage:(SKSpriteNode*)image {
    if (self = [super init]) {
        _image = image;
        [self initImage];
    }
    return self;
}

-(void) initImage {
    _image.zPosition = -1;
    _image.alpha = 1;

    float width = _image.frame.size.width, height = _image.frame.size.height;
    SKTexture *texture = [_image texture];
    SKSpriteNode *mask = [SKSpriteNode spriteNodeWithTexture:texture size:CGSizeMake(width, height)];
    mask.zPosition = 1;

    _shape = [SKSpriteNode spriteNodeWithColor:[NSColor whiteColor] size:CGSizeMake(width, height)];
    _shape.zPosition = 2;
    _shape.alpha = 0;


    _cropNode = [SKCropNode node];
    _cropNode.maskNode = mask;
    [_cropNode addChild:_shape];
    [_cropNode addChild:_image];
    [self addChild:_cropNode];
}

-(void) flashWhite {
    SKAction *showWhite = [SKAction fadeAlphaTo:1.0 duration:0];
    SKAction *hideImage = [SKAction fadeAlphaTo:0 duration:0];
    SKAction *fadeOut = [SKAction fadeAlphaTo:0 duration:0.2];
    SKAction *fadeIn = [SKAction fadeAlphaTo:1 duration:0.2];

    [_shape runAction:[SKAction sequence:@[showWhite, fadeOut]]];
    [_image runAction:[SKAction sequence:@[hideImage, fadeIn]]];
}

@end