1

I use the following piece of code to generate SKNodes periodically. Is there a way to make the period of generation of these SKNodes random. Specifically, how do I make the "delayFish" in the following code an action with a random delay?

[self removeActionForKey:@"fishSpawn"];
SKAction* spawnFish = [SKAction performSelector:@selector(spawnLittleFishes) onTarget:self];
SKAction* delayFish = [SKAction waitForDuration:3.0/_moving.speed];
SKAction* spawnThenDelayFish = [SKAction sequence:@[spawnFish, delayFish]];
SKAction* spawnThenDelayFishForever = [SKAction repeatActionForever:spawnThenDelayFish];
[self runAction:spawnThenDelayFishForever withKey:@"fishSpawn"];
CodeSmile
  • 64,284
  • 20
  • 132
  • 217
RawMean
  • 8,374
  • 6
  • 55
  • 82

2 Answers2

6

ObjC:

First set an average delay and range...

#define kAverageDelay    2.0
#define kDelayRange      1.0     // vary by plus or minus 0.5 seconds

and then change your delayFish action to this...

SKAction* delayFish = [SKAction waitForDuration:kAverageDelay withRange:kDelayRange];

Swift:

First set an average delay and range...

let averageDelay:TimeInterval = 2.0
let delayRange:TimeInterval = 1.0     // vary by plus or minus 0.5 seconds

and then change your delayFish action to this...

let delayFish = SKAction.wait(forDuration:averageDelay, withRange:delayRange)
0x141E
  • 12,613
  • 2
  • 41
  • 54
  • Did you test it? Perhaps you will need increase kDelayRange to notice a difference. From Apple's documentation, "Each time the action (waitForDuration:withRange) is executed, the action computes a new random value for the duration. The duration may vary in either direction by up to half of the value of the durationRange parameter." – 0x141E Jul 25 '14 at 18:05
  • It works. Sorry I didn't read carefully and I thought you are suggesting the same thing that Akaino did. Thanks much. – RawMean Jul 26 '14 at 02:57
0

Insert a random float instead of a fixed one.

In your case something like this:

double value = ((double)arc4random() / ARC4RANDOM_MAX) 
   * (maxValue - minValue)
   + minValue;

SKAction* delayFish = [SKAction waitForDuration:value/_moving.speed];

I see. This won't work in your case as repeatActionForever will run with the last created random value. Forever. Maybe try this instead. I'm not sure if this works though:

SKAction* delayFish = [SKAction waitForDuration: (((double)arc4random() / ARC4RANDOM_MAX) * (maxValue - minValue)+ minValue)/_moving.speed];

I suggest making the random value an own method though.

-(double) getRandomValue(){
    return (((double)arc4random() / ARC4RANDOM_MAX) * (maxValue - minValue)+ minValue);
}

EDIT:

Here is a link to a similar issue. Maybe that might help. Sorry!

SKAction *randomXMovement = [SKAction runBlock:^(void){
    NSInteger xMovement = arc4random() % 20;
    NSInteger leftOrRight = arc4random() % 2;
    if (leftOrRight == 1) {
        xMovement *= -1;
    }
    SKAction *moveX = [SKAction moveByX:xMovement y:0 duration:1.0];
    [aSprite runAction:moveX];
}];

SKAction *wait = [SKAction waitForDuration:1.0];
SKAction *sequence = [SKAction sequence:@[randomXMovement, wait]];
SKAction *repeat = [SKAction repeatActionForever:sequence];
[aSprite runAction: repeat];

Source: SKAction: How to Animate Random Repeated Actions

Community
  • 1
  • 1
Akaino
  • 1,025
  • 6
  • 23
  • thanks but this code does not make the time interval between the spawning the nodes (through spawnLittleFishes) random. The period is still fixed. – RawMean Jul 25 '14 at 06:10
  • No. It makes the delayFisch an action with a random delay. As you wanted :) Could you show the whole method to see how you implemented the random value? – Akaino Jul 25 '14 at 06:21
  • Thanks again, but your second method is equivalent to the first one and has the same issue. the problem with this approach is that the delayFish action is created once and with a fixed value. – RawMean Jul 25 '14 at 06:56
  • You are right. I edited again. There was a similar issue on SO so that might help you! – Akaino Jul 25 '14 at 06:59