1
votes

i have an SKAction sequence involving two actions. 1) wait for time according to variable 2) spawn object

SKAction *sequence = [SKAction sequence:@[
                                        wait,
                                        addObject]];

this action is set to run forever. however, i want the wait duration to change according to updating the variable, but it stays constant as it does not take the new variable when running forever

[self runAction:[SKAction repeatActionForever:sequence]];

How do i make it steadily increase the value, therefore increasing the rate of object spawning?

Thanks

2

2 Answers

3
votes

There are two solutions:

  1. Create the sequence or at least the wait action anew every time you need it. Actions are supposed to be discarded and re-used frequently.
  2. If this poses a performance problem and given that you already have a reference to the sequence, you can also change its speed variable. This ought to alter the wait time accordingly, ie if speed is 0.5 the wait time should double.

Example for solution 1:

CGFloat waitDuration = (value to be determined by you);
SKAction *sequence = [SKAction sequence:@[
                                        [SKAction waitForDuration:waitDuration],
                                        addObject]];

Example for solution 2:

SKAction *sequence = [SKAction sequence:@[
                                        wait,
                                        addObject]];

// half the speed, double the wait time
sequence.speed = 0.5; 

// or if you need to derive speed from waitDuration (which must be >0.0)
sequence.speed = (1.0 / waitDuration);

In case the sequence isn't affected by speed try setting the wait action's speed instead.

0
votes

So I followed LearnCocos2D's answer, but I made a slight modification, which I think works great. It works for my purpose, so I thought to put it out there.

What I did was this:

//This is the boring bits for creating the SKSpriteNode 
    headsNode = [SKSpriteNode spriteNodeWithTexture:[self.textureAtlas firstObject]size:CGSizeMake(100, 100)];
    headsNode.position = CGPointMake(CGRectGetMidX(self.frame)*0.5, CGRectGetMidY(self.frame)-coinSize/2);

    headsNode.name = @"Heads";
    [self addChild:headsNode];

// I added a timer with winkWaitingTime as interval. This is the variable
// to change. Set this to something at the beginning.
NSTimer *timered= [NSTimer scheduledTimerWithTimeInterval:winkWaitingTime target:self selector:@selector(timerFired:) userInfo:nil repeats:YES];
    [timered fire];
}

-(void)timerFired:(NSTimer*)timer{
//In the NSTimer Selector, I set the timer interval / SKAction waiting interval to a random
// number
    winkWaitingTime =[[SharedInfo sharedManager] randomFloatBetween:3 and:8];
    [headsNode removeAllActions];
//I thought it's best to remove the actions JIC :) 
    [headsNode runAction:[self returnActionForAnimationKey:headsNode.name]];
    NSLog(@"winktimer: %f",winkWaitingTime);
}
-(SKAction*)returnActionForAnimationKey:(NSString*)animationKey{
    CGFloat waitDuration;
//This is for just to prevent timer fire interfering with the SKAction
//This will make the SKAction waiting time shorter than NSTimer Fire rate
    if (winkWaitingTime >4) {
        waitDuration = winkWaitingTime-3;
    }else{
        waitDuration = 1;
    }

    SKAction *sequence = [SKAction sequence:@[
                                              [SKAction waitForDuration:waitDuration],
                                              [SKAction animateWithTextures:self.textureAtlas timePerFrame:0.1f resize:NO restore:YES]]];

    return sequence;
}

As I said, it works for me, and by changing the winkWaitingTime, and a bit of prevention management, it works.

I hope you find it useful as well. In terms of memory management, my Xcode is showing stable CPU / Memory / Battery usage, so there's no increase in use.

NOTE: After receiving a comment, I thought it's best to discuss the use of NSTimer. If you need to have something done "externally", i.e. independent to the view or scene, then I'd use the NSTimer (that was my case). But you'd have to implement the pausing and unpausing for the timer as well. (You'd have to invalidate the NSTimer to stop, and reschedule a new one, or have it as a variable and reschedule the same one). Otherwise, use the SKAction and you won't need to pause and unpause the NSTimer.