8

I'm trying to colorize a spriteNode (in this case its named background) using sprite kit but cant get the color to change. I have a sprite that I want to colorize. I'm changing the color property of the sprite as well as the color blending factor. When I run the app nothing happens though. the color remains the same (its black right now). below is the code I'm using to change the color:

background.anchorPoint = CGPointMake(0, .5);
background.position = position;

// ...

// this does not seems to be doing anything at all
background.color = [SKColor redColor];
background.colorBlendFactor = 1.0f;

did I miss something? I read through the docs and it seems like a pretty simple process. I believe all I need were those 2 lines, but it doesnt have any effect. Does anyone know why this would not be working? The texture image has a lot of transparency, could that be causing the issue? Ive tried this on different sprites and it never works.

Confused
  • 6,048
  • 6
  • 34
  • 75
Stone Preston
  • 1,828
  • 4
  • 20
  • 35
  • Have you tried not setting a texture on the same SpriteNode? Have you tried setting the Scene's color to a different color to see if your SpriteNode is black, or if you can't see it and are instead seeing the Scene's background? – Attackfarm Jul 27 '14 at 21:09
  • Have you tried running one of the SKAction methods to colorize it? – uchuugaka Jul 27 '14 at 22:13
  • yes ive tried running an action to colorize, still nothing – Stone Preston Jul 28 '14 at 01:01

3 Answers3

12

Something like this:

    bug.color = SKColorWithRGB(128, 128, 128); 
    bug.colorBlendFactor = 1.0f;

Should definitely tint the sprite of choosing. The thing is that this is non intensive blend. Using a CIFilter with an SKEffectsNode is very very intensive for such a simple task.

I have an example below that blends a sprite with a red tinting, making the the sprite red tinted rather it's original color of orange:

    - (instancetype)init
{
    if (self = [super init]) {
        self.physicsBody.categoryBitMask = PCFireBugCategory;
        self.physicsBody.collisionBitMask = PCPlayerCategory | PCWallCategory | PCBreakableCategory | PCBoundaryCategory;
        //Keeps the bugs from sliding too far when bumped
        self.physicsBody.linearDamping = 1;
        self.physicsBody.angularDamping = 1;
        self.color = [SKColor redColor];
        self.colorBlendFactor = 0.45;
    }

    return self;
}

I would also like to point out that this class is a subclass of SKSpriteNode.

Attached below is an example where I've applied the red tint using the exact code above. enter image description here

Raywenderlich has a nice quote describing blending effects:

Note: Because the tint color is multiplied by the original color to get the final result, if you set the color of a sprite to blue the end result won’t necessarily be blue – it depends on what the original color is. Because of this, if you want to dynamically set a sprite’s color to a specific color, it is convenient to make the source color of the sprite white (like the cat in Zombie Conga). If you want parts of your sprite to be different colors, you can also split your sprite into different parts, each of which you tint to a different color. For more information, see the Beat ‘Em Up Game Starter Kit available at raywenderlich.com.

TheCodingArt
  • 3,436
  • 4
  • 30
  • 53
  • 1
    ok ive tried changing the source color of one of my sprite images to white and after making that change the color does change. so it wasnt working because my images were black. guess il just change the ones I need to colorize to white. thanks for the help – Stone Preston Jul 28 '14 at 01:17
1

Quite an old question, but I came across this issue from time to time. The colorBlendFactor is not what one might expect, that it recolours sprites. In fact, the new colour, blended over the old one, heavily depends on the color that was at that position before.

To overcome this, I use overlying sprites (as mentioned before) and the alpha values of the underlying and the overlaying sprite to create the expected colours.

For example to blend the following sprite slowly from blue to gray, I use two sprites: blue cloudgrey cloud

(The blue sprite is the original one and the grey one is just a version of the blue one, manipulated with the ColorSync Utility on the Mac.)

and this code (Swift):

// Load the two Textures
let TEXTURE_CLOUD_BLUE = SKTexture(imageNamed: "cloud blue")
let TEXTURE_CLOUD_GRAY = SKTexture(imageNamed: "cloud gray")

// Create an Action. Note that the second Action takes longer to finish. This makes the blend to grey slower and easier to watch
let fadeToGray = SKAction.group([
    SKAction.runAction(SKAction.fadeOutWithDuration(1.0), onChildWithName: "cloudBlue"),
    SKAction.runAction(SKAction.fadeInWithDuration(2.0), onChildWithName: "cloudGray"), // Slower fade in
    SKAction.waitForDuration(2.0) // Actions on children return immediately
    ])

// Init super sprite node
super.init(texture: nil, color: UIColor.clearColor(), size: size)

// Add blue cloud
let cloudBlue = SKSpriteNode(texture: TEXTURE_CLOUD_BLUE, size: size)
cloudBlue.alpha = 1.0 // Show immediately
cloudBlue.name = "cloudBlue"
addChild(cloudBlue)

// Add grey cloud
let cloudGray = SKSpriteNode(texture: TEXTURE_CLOUD_GRAY, size: size)
cloudGray.alpha = 0.0 // Don't show at start
cloudGray.name = "cloudGray"
addChild(cloudGray)

// Run Action to fade away
self.runAction(fadeToGray)

Quite some code. I hope the idea comes across. You can play around with the times in the action or use fadeAlphaTo/By instead of fadeIn/OutWithDuration to produce the desired effects.

jboi
  • 11,324
  • 4
  • 36
  • 43
-4

SKColor is killing all other pixels rather than chosen colors' pixels. Therefore, if your image doesn't contain any red pixels, then [SKColor redColor] is not gonna work. I suggest you to use CIHueAdjust, which is a CIFilter.

  • Can you please reference sources detailing this, because this is completely incorrect. CIFilters being applied with an effects node for something like this provides quite a hit to performance and is not remotely necessary unless you are going to apply filter like effects on a large scale of different nodes. – TheCodingArt Jul 27 '14 at 21:01
  • I am not saying that CIFilter can be applied without effect nodes. SKColor and UIColor diminishes the pixel density of other pixel colours to zero. If it is completely wrong try to use [SKColor redColor] on a black coloured image and observe the effects yourself before judging. – Ahmet Hayrullahoglu Jul 27 '14 at 21:21
  • Algorithm? SKColor is just a macro for either NSColor on OS X or UIColor on iOS – uchuugaka Jul 27 '14 at 21:29
  • @uchuugaka I think he was referencing the blending algorithm in the background. "I am not saying that CIFilter can be applied without effect nodes." and I wasn't saying that you weren't saying this, what I was saying is that a tint is applied to the color values of the current texture... of course you won't see a tint on black any color blended with black is black..... The way you described this is wrong. Colors aren't 'turned off'.. they are blended.... – TheCodingArt Jul 27 '14 at 22:11
  • Read my answer, I've added a quote explaining effects for blending – TheCodingArt Jul 27 '14 at 22:14
  • looks like you are correct. since my images are black to begin with, the colorBlendFactor makes no difference. I changed the original color of one my images to white, and it works with the white – Stone Preston Jul 28 '14 at 01:14
  • thanks, I am glad that it helped in understanding of how does it work – Ahmet Hayrullahoglu Jul 28 '14 at 08:09