Here's the code. I hope the comments clarify it enough. If not, i apologize; My English isn't great, but my explanation skills are simply terrible. I've also uploaded part of a screenshot of the app to illustrate what i mean with cloud 'layers' (in this example i'm using 3 different depth layers): http://imageshack.us/photo/my-images/812/layerample.png/
The info button on top-left shows the UIScrollView i was talking about, which allows me to edit constants which alter the clouds' behaviour to easily test in-app what looks best. That way my designer can more easily find that out; Since i'm barely creative, it generally works out better if he tests that ;)
#import "CloudLayer.h"
#import "RDCloud.h"
@implementation CloudLayer
//Some 'constants' i can edit from a UIScrollView within the app to alter the clouds' //behaviour. That way i can edit some number without having to rebuild each time.
@synthesize speedModifier;
//The speed with which the clouds move
@synthesize numberOfClouds;
//Total amount of clouds
@synthesize numberOfLayers;
//Amount of depth layers the clouds are distributed amongst
@synthesize scale;
//How much longer the most distant layer is than the closest
@synthesize totalCloudHeight;
//Total difference of height between the closest and furthest layer.
@synthesize increments;
//Amount with which each cloud's location increases compared to the previous.
- (id)init
{
self = [super init];
if (self) {
cloudsArray = [[NSMutableArray alloc]init]; //The array used to hold the clouds
//The loop i'm using to give the clouds different images. Currently 3 different, though
//it's designed for more different images.
int s = 0;
for (int i=0; i<30; i++) {
CCTexture2D *cloudImage;
switch (s) {
case 0:
cloudImage = [[CCTextureCache sharedTextureCache]addImage:@"Cloud1.png"];
break;
case 1:
cloudImage = [[CCTextureCache sharedTextureCache]addImage:@"Cloud2.png"];
break;
case 2:
cloudImage = [[CCTextureCache sharedTextureCache]addImage:@"Cloud3.png"];
break;
default:
break;
}
RDCloud *cloud = [RDCloud spriteWithTexture:cloudImage];
//RDCloud is my CCSprite subclass
[cloud setOpacity:0];
[self addChild:cloud];
[cloudsArray addObject:cloud];
s++;
if (s>2)
{
s=0;
}
}
[self schedule:@selector(tick:)];
}
return self;
}
- (void)tick:(ccTime)dt
{
cloudPosition += speedModifier * dt * 0.03f;
//CloudPosition is the one point moving along the line.
int partDifference = ((scale * 620) - 620) / numberOfLayers;
//How much longer each layer's line is compared to the previous one
int totalLength = (numberOfLayers/2) * (numberOfLayers-1) * partDifference+numberOfLayers*620;
//totalLength: all the layers added to each other
if (cloudPosition > totalLength) {
cloudPosition = 0;
}
else if (cloudPosition < 0)
{
cloudPosition = totalLength;
}
for (int i=0; i<numberOfClouds; i++) {
RDCloud *cloud = [cloudsArray objectAtIndex:i];
int cloudLayer = 0;
double newPos = cloudPosition+increments*totalLength*i;
while (newPos>totalLength) {
newPos -= totalLength;
}
for (int p = 0; p < numberOfLayers+1; p++) {
//Loop to determine in which 'layer' this particular cloud is.
if (newPos<(620+((p+1)/2*p*partDifference)+p*620)) {
if (p>0) {
double correction = (620+(double)(p*partDifference));
newPos = (newPos-(620+(p/2)*(p-1)*partDifference+(p-1)*620));
newPos = newPos/correction;
newPos = newPos * 620 ;
}
cloudLayer = p;
posDone = true;
break;
}
}
[cloud setRDScale:1/((scale-1)/(double)numberOfLayers*cloudLayer+1)];
[self reorderChild:cloud z:numberOfLayers-cloudLayer];
double cloudHeight = 430-((totalCloudHeight)*2/numberOfLayers)*cloudLayer;
[cloud setPosition:CGPointMake(newPos-150*cloud.scale, cloudHeight)];
}
}
@end