3

I am developing a cocos2d based app with a space background in which I am exploiting a CCQuadParticleSystem to make blinking stars. I have generated this particle system with ParticleDesigner. As soon as I load the particle system white dots representing stars start appearing in the background and after a while they fade out so that, after few seconds in which the particle system reaches the regime state, a night sky full of stars comes out.

My problem is that I would like to know if there is a way to make the particle system starting from a specific time in the future (for instance t0 = 3sec) so that I do not have to wait to have all the starts blinking.

I hope I have clearly explained the problem

thank you in advance

Andrea

Andrea Sindico
  • 7,358
  • 6
  • 47
  • 84
  • 1
    did you find a solution for this? i*m experiencing the same problem (with snow) – Alex Milde Aug 08 '11 at 14:43
  • Alex have have you managed to start your particle system from a time in the future? – Andrea Sindico Sep 02 '11 at 18:22
  • unfortunately not. otherwise i would have postet the code. (like every coder should ;) i think the only workaround is messing with the update time / gravity until the screen is filled and setting the updatetime / gravity to normal. (not tested but might work) – Alex Milde Sep 08 '11 at 08:49

5 Answers5

7

I did this and it worked exactly the way I wanted it to.

for (int i = 0 ; i < 300 ; i++)
    [emitter update:.1];
kokernutz
  • 268
  • 3
  • 9
  • 1
    This worked for me too, I don't know why you were downvoted. It basically fast-forwards the emission of the initial particles, which makes it appear as if you had started from a point later in time. – Corentin S. Oct 27 '13 at 16:44
  • This is most certainly the correct answer. Thank you! – Jarad DeLorenzo Mar 22 '16 at 11:52
2

Have you tried a

id actions = [CCSequence actions:[CCDelayTime actionWithDuration:3.0f],
              [CCCallFunc actionWithTarget:self selector:@selector(onStallComplete)],
              nil];
[self runAction:actions];

ok, granted it is probably abusing the original intent of the API's , but is useful
watch for re-entrancy in onStallComplete if you have multiple such delayed reactions.

note: newbie at SO, hope the code snippet comes out looking right

YvesLeBorg
  • 9,070
  • 8
  • 35
  • 48
  • I think you want to use CCCallFuncN instead of CCCallFunc. – Imran Sep 03 '11 at 17:58
  • @imran ... yes, I was doing this from memory, just to get the idea across. My own usages of this range from ultra simple (as in this example) to tricky multiplexed versions when the situation calls for it. – YvesLeBorg Sep 03 '11 at 19:19
0

I do not think there is a way to fast forward your particle system 3 seconds into the future. Alternatively I can imagine two different solutions depending on your circumstances:

  1. Load the scene with the particle behind another scene (e.g. an empty black scene). After 3 seconds switch to the scene with the now nice looking particle effect. This could work f it is ok for you that the user needs to wait for 3 seconds and you only do not want them to see the particle system while everything is clunked together or if you have another scene before the scene with the particle system anyway.
  2. Record the particle system, store it in a file then replay it in your scene. With recording I mean store the position and color of each of your particles. The drawback is, that it will look the same everytime and if you want to run it longer than what you recorded you need to make sure replaying it in a loop still looks good.
gebirgsbärbel
  • 2,327
  • 1
  • 22
  • 38
0

I can't think of a way to implement this directly, but could you try something like this as a workaround? I'm afraid I haven't been able to test this yet due to other errors, but working on it.

{ 
    ...

    //This attempts to make 3 seconds pass 100 times quicker
    [[CCScheduler sharedScheduler] setTimeScale:100];
    [self schedule:@selector(cancelIncreasedTimeScale) interval:3];

    ...
}


int numberOfTimesCancelled = 0;
-(void) cancelIncreasedTimeScale
{
    numberOfTimesCancelled ++;
    //Two because the scheduler is also called straight away? Remove if it's only called after waiting an initial (3/100) seconds
    if (numberOfTimesCancelled == 2) {
        [self unschedule:@selector(cancelIncreasedTimeScale)];
        [[CCScheduler sharedScheduler] setTimeScale:1];
    }
}

The issue I do worry about is the other items on your scene would also run 100 times faster. Is that an issue?

James Webster
  • 31,873
  • 11
  • 70
  • 114
  • I have actually tried it but it doesn't seem to work as I expected. Have you tried it? does it work to you? I have also tried to set the elapsed field as a @property in order to call this [particleSystem setElapsed: 3] but it does not work. – Andrea Sindico Sep 03 '11 at 10:08
0

I assume you are using some kind of updateWithDelta: method in your game loop in order to update the particles. If you want the particles to start after a certain interval, make your own timer.

Edit: Based on your comment below, my method is still good, it just needs some tweaking. You need only remove the condition in the updateWithDelta: method on the particle system. That way, it will still update for those 3 seconds, but will not render, and therefore look the way you are describing.

In the .h file:

BOOL particleShouldUpdate;
float particleTimer;

In your init method:

particleShouldRender = NO;
particleTimer = 3.0f;

In your updateWithDelta: method:

if(!particleShouldRender){
  particleTimer -= delta;
  if(particleTimer < 0){
    particleShouldRender = YES;
  }
}
// update your particle.

Finally, in your render method:

if(particleShouldRender){
  // render your particle.
}

Note that from this point, if you want to stop it rendering, you need only reset the 2 variables like as in the init method, and the same effect will occur.

EDIT2: Upon further clarification, we only need to adapt the init method of your particle. I will make 2 assumptions here, and you need only change them slightly to fit your needs. Suppose that your update cycle is 60 frames per second, the minimum particle lifespan is 1.01, and that you want 3 seconds of updates before you start the game. Then in the init method, try:

for(float delta = 0.0f; delta < 3.0f; delta += (1/60)){
  [particle updateWithDelta:(float)(1/60)];
}

This will update your particle like it normally would, but without rendering at each interval, and before anything else gets updated. Alternatively, if you are worried about speed when updating your particle, you can try:

for(int i = 0; i < 3; i++){
  [particle updateWithDelta:1];
  [particle updateWithDelta:0.02];
}

This will be faster, but may have a few issues depending on your particles parameters.

EDIT3: So looking into this further, cocos2D does not let you do this for some reason. I found a similar question online to this, and they suggested you play with the posVar and speed to make them large enough while you are transitioning into the scene, and once you have fully transitioned into the scene, reset the values to normal. You may want to give that a try!

Hope that Helps!

msgambel
  • 7,320
  • 4
  • 46
  • 62
  • Hi and thank for your answer, however i do not want to start the particle system in the future. I want it to start from the beginning of the app but i'd like it to start as if it was running from a time (for instance 3 seconds). – Andrea Sindico Sep 04 '11 at 14:53
  • Wait a second, do you mean you want to start the app, and have a particle that is running right away, that looks as if it has been running for 3 seconds already, even though the scene just started? – msgambel Sep 05 '11 at 00:52
  • yes that is exactly what I meant. The problem is that I am using the particle system to represents a sky full of stars. When the particle system starts there are no stars but after a few seconds (i.e. 3) it fills the screen with blinking white dots. What I would like is avoiding the transitory time and starting the particle system as if 3 seconds were already passed. Is there any way to do that? – Andrea Sindico Sep 05 '11 at 07:59
  • the Idea is good but: I am using CCQuadParticleSystem which extends CCParticleSystem and only inherits the update method (not the updateWithDelta) however the update method actually takes one parameter ((ccTime) dt) where ccTime is float. I have therefore tried the code you suggest by invoking update instead of updateWithDelta. Unfortunately it does not work, I continue to find the particle system as if nothing happened :( – Andrea Sindico Sep 05 '11 at 19:28
  • I made a typo in my answer, with updating by delta instead of a the fixed (1/60). Looking into the code for `-(void) update: (ccTime) dt;`, it seems like this shouldn't have a problem. There is nothing about the method that is tied to the global `updateWithDelta:` method. Are you sure that you initialized the particle *BEFORE* you did the above loop? – msgambel Sep 05 '11 at 19:41
  • I have instantiated it with the particleWithFile method that should initialize it – Andrea Sindico Sep 05 '11 at 20:02
  • I found a similar post online, and you should check it out. – msgambel Sep 05 '11 at 20:12
  • Great! I'm glad I could help! I'm very surprised at how much work was involved in this. You'd think that it would be much easier! Cocas should really implement something like this, where you can give a start time for your particle. I think it would be a great feature! – msgambel Sep 06 '11 at 06:23
  • I can't understand why an answer that proclaims itself to be useless would get so many up votes. – e.w. parris Jul 06 '14 at 13:22