Specify random particle start colour with no animated change?
Asked Answered
V

2

7

Is there a way to have particles spawn with a random per particle colour based on the current "Color Ramp"? The particles do not change colour over their lifespan, they are simply assigned a colour from somewhere along the "Color Ramp" at birth and keep that colour until they die.

The result of this would be a mix of particles at birth with blend colours from RED through to BLUE.

Color Blend

In my tests I only seem to be able to get the behaviour where particles spawn as RED and then gradually turn to BLUE as the approach the bottom of the screen.

enter image description here Falling Leaves

Vergos answered 6/11, 2013 at 13:22 Comment(4)
You don't wish for them to animate to the bottom of the screen but stay in place and change colors?Giblet
@JohnRiselvato - With the colour ramp the particles animate from red (top) to blue (bottom). What I was after is not having the particles animate in color at all, but rather spawn with a constant color (from the ramp) and then keep that color for their entire lifespan. Like autumn leaves falling from a tree, some are green, some are yellow, some are orange, they just start with their individual color and fall (they don't change color as they fall)Vergos
I used snow as the original, then changed the sprite to the leaf (ill, add the *.png above)Vergos
I think the problem is that the colour ramp only works over time, all the particles always start red (and then you have the option to blend from red to blue) I don't think this gives you the ability to assign a fixed blend colour (based on the ramp) on a per particle basis.Vergos
G
8

Well, It looks like you can't use a predefined sks file for the SKEmitterNode... I was able to figure this out by programmatically creating the SKEmitterNode. The reason why is because it doesn't look like when you initiate an SKEmitterNode with an sks, it doesn't respond to setParticleColor: but programmatically initiating one does.

Now today, this past hour, was the first time I ever messed with an SKEmitterNode, so you'll have to bear with me because I couldn't figure out how to get the snow effect perfect, but I'm sure you can just mess with the values an SKEmitterNode allows you to change.

In any case, I'm going to assume that the SKEmitterNode is presented on the SKScene (that's the only way I know how to get your desired effect).

First you'll need to make you're SKEmitterNode a global/property/etc because you'll need access to it later.


In the MyScene.m:

@implementation MyScene {
    SKEmitterNode* leafEmitter;
}

-(id)initWithSize:(CGSize)size {    
        leafEmitter = [[SKEmitterNode alloc] init];
        [leafEmitter setParticleTexture:[SKTexture textureWithImageNamed:@"saFMB.png"]];
        [leafEmitter setParticleBirthRate:10];
        [leafEmitter setScale:0.5];
        [leafEmitter setYAcceleration:-10.0];
        [leafEmitter setParticleSpeedRange:100];
        [leafEmitter setParticleLifetimeRange:100.0];
        [leafEmitter setParticlePositionRange:CGVectorMake(self.size.width, self.size.height)];
        [leafEmitter setPosition:CGPointMake(100, 400)];
        [leafEmitter setParticleBlendMode:SKBlendModeAlpha];
        [self addChild:leafEmitter];
}

So what i've done here is programatically created the particle effect, this is where you'll change the animation/speed/etc variables to get the best particle effect you are looking for. I would suggest reading this for more details.


Now remember how I said that it needs to be presented on the SKScene? Well that's because we are going to be taking advantage of the update:(CFTimeInterval)currentTime function that comes along with an SKScene.

Inside the update:(CFTimeInterval)currentTime is the location where we will be changing the SKEmitterNode's color. Since this update function is called every frame it makes it easy to change the color without any fancy timers or such. Not sure if this is a good idea, but it's the idea that counts.

-(void)update:(CFTimeInterval)currentTime {
[leafEmitter setParticleColor:[UIColor colorWithHue:drand48() saturation:1.0 brightness:1.0 alpha:1.0]];
[leafEmitter setParticleColorBlendFactor:1.0];
    /* Called before each frame is rendered */
}

In this case, we are changing the color to a random RGB value but i'll let you select the colors yourself.


In return this is what my code has produced:

enter image description here


All this said, it doesn't look like you can get the effect you want solely using the particle interface unfortunately.

Giblet answered 6/11, 2013 at 17:23 Comment(2)
Hi John, thank you for your time and effort in putting that answer together. I see what your doing and it looks good to me, I will give it a try in the morning. Much appreciated, perfect answer.Vergos
If you set the 'particleColorSequence' variable of the SKEmitterNode to nil then the SKParticleColor is not ignored anymore. Creating an SKS typically sets it to non-nil causing other color attributes to be ignored.Systemic
V
2

What I've found works, without needing to add code to an update() function is to apply the following changes to the emitter.

@john-riselvato is correct (even now, after 7 years) use the editor to define this, but you can get the desired effect with the following code:

import Foundation
import SpriteKit

class RandomColorEmitterNode : SKEmitterNode {

    override init() {
        super.init()
    
        self.particleColorSequence = nil
        self.particleColorBlendFactorSequence = nil
        self.particleColorBlueRange = 255
        self.particleColorGreenRange = 255
        self.particleColorRedRange = 255
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    
        self.particleColorSequence = nil
        self.particleColorBlendFactorSequence = nil
        self.particleColorBlueRange = 255
        self.particleColorGreenRange = 255
        self.particleColorRedRange = 255
    }
}

This way, with a simple call to:

if let emitter = RandomColorEmitterNode(fileNamed: "flower.sks") {
    self.addChild(emitter)
}

the emitter is initially loaded from the SKS file you create in the editor, and then the color attributes are overriden by the class.

Vagabond answered 24/3, 2021 at 23:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.