We have a SpriteKit background node built in Objective-C. Our application builds the tiles(a transparent png image), loops the tiles and changes the background color based on the user's heart rate. There is also a optimise titles function but we found it does not have much of an impact if we disable. Here is a link to a GIF which shows the background function in action - http://gph.is/2auqNjW
Our CPUs usage and Energy is being crushed by these two functions below (actBuildNode & addBackgroundTilesInit). Any advice or suggestions to optimize would be greatly appreciated. We know it's these two functions because if we disable them the CPU usage is decreased by 70% and GPU goes down to 2%. The goal is to simulate moving water in the background, which changes color based on user's heart rate zone.
-(void)actBuildNode {
[Helper logToServer:@""
withFunction:[NSString stringWithFormat:@"%s", __PRETTY_FUNCTION__]
withLine:@(__LINE__)];
flSceneSteps = 0;
flNumberSteps = 0;
intStepAmount = 0;
self.flStepFactor = 0;
[self runAction:[SKAction colorizeWithColor:[Helper UIColorFromHex:0x577C80 alpha:1.0f] colorBlendFactor:1.0f duration:0.f]];
NSInteger intMWorkoutValue = [[CoreMachine sharedInstance].pfWorkoutType.valueType integerValue];
switch (intMWorkoutValue) {
case iWorkoutTypesDistance:
{
flNumberSteps = [[CoreMachine sharedInstance].pfWorkoutType.value floatValue];
flSceneSteps = flNumberSteps / 50;
intStepAmount = 50;
self.size = CGSizeMake(rectWindow.size.width * flSceneSteps, rectWindow.size.height);
}
break;
case iWorkoutTypesTimed:
{
flSceneSteps = [[CoreMachine sharedInstance].pfWorkoutType.value floatValue] / 60;
flNumberSteps = flSceneSteps * 60;
intStepAmount = 30;
self.size = CGSizeMake(rectWindow.size.width * (flSceneSteps * 4 + 1), rectWindow.size.height);
}
break;
case iWorkoutTypesCustom:
{
switch ([[CoreMachine sharedInstance].pfIntervalSegment.valueType integerValue]) {
case iWorkoutSegmentTimed:
{
flSceneSteps = [[CoreMachine sharedInstance].pfIntervalSegment.value floatValue] / 60;
flNumberSteps = flSceneSteps * 60;
intStepAmount = 30;
self.size = CGSizeMake(rectWindow.size.width * (flSceneSteps * 4 + 1), rectWindow.size.height);
}
break;
case iWorkoutSegmentDistance:
{
flNumberSteps = [[CoreMachine sharedInstance].pfIntervalSegment.value floatValue];
flSceneSteps = flNumberSteps / 50;
intStepAmount = 50;
self.size = CGSizeMake(rectWindow.size.width * flSceneSteps, rectWindow.size.height);
}
break;
default:
break;
}
}
break;
case iWorkoutTypesJustRow:
{
flNumberSteps = 20000;
flSceneSteps = flNumberSteps / 50;
intStepAmount = 50;
self.size = CGSizeMake(rectWindow.size.width * flSceneSteps, rectWindow.size.height);
}
break;
default:
{
}
break;
}
self.color = [UIColor blackColor];
self.scene.scaleMode = SKSceneScaleModeAspectFill;
self.anchorPoint = CGPointMake(0, 0);
self.position = CGPointMake(0, 0);
[self runAction:[SKAction moveToX:0 duration:0] completion:^{}];
self.zPosition = 0;
lastFlMoveX = 0;
[self addBackgroundTilesInit];
[self addMeterMarkers];
}
-(void)addBackgroundTilesInit {
SKSpriteNode *backgroundA = (SKSpriteNode *)[self childNodeWithName:@"BackgroundA"];
if (backgroundA) {
[backgroundA removeAllChildren];
[backgroundA removeAllActions];
[backgroundA removeFromParent];
backgroundA = nil;
}
SKSpriteNode *backgroundB = (SKSpriteNode *)[self childNodeWithName:@"BackgroundB"];
if (backgroundB) {
[backgroundB removeAllChildren];
[backgroundB removeAllActions];
[backgroundB removeFromParent];
backgroundB = nil;
}
backgroundA = [[SKSpriteNode alloc] initWithColor:[Helper UIColorFromHex:0x577C80 alpha:1.0f] size:CGSizeMake(rectWindow.size.width * 4, 2 * rectWindow.size.height)];
backgroundA.name = @"BackgroundA";
backgroundB = [[SKSpriteNode alloc] initWithColor:[Helper UIColorFromHex:0x577C80 alpha:1.0f] size:CGSizeMake(rectWindow.size.width * 4, 2 * rectWindow.size.height)];
backgroundB.name = @"BackgroundB";
//SKSpriteNode *colorPanel = [[SKSpriteNode alloc] initWithColor:[Helper UIColorFromHex:0x1B4E58 alpha:1.0f] size:CGSizeMake(SCREEN_WIDTH, SCREEN_HEIGHT)];
//colorPanel.name = @"nodeColorPanel";
SKTexture *backgroundTextureA = [SKTexture textureWithCGImage:[UIImage imageNamed:@"GrayWaterImage-2"].CGImage];
SKTexture *backgroundTextureB = [SKTexture textureWithCGImage:[UIImage imageNamed:@"GrayWaterImage-2"].CGImage];
for (int i = 0; i < 3; i++) {
//DLog(@"i:%i", i);
intCurrentBackground = i;
SKSpriteNode *nodeBackgroundTileA = [SKSpriteNode spriteNodeWithTexture:backgroundTextureA size:CGSizeMake(rectWindow.size.height, rectWindow.size.height)];
nodeBackgroundTileA.name = [NSString stringWithFormat:@"BackgroundA_%i", intCurrentBackground];
nodeBackgroundTileA.scene.scaleMode = SKSceneScaleModeAspectFill;
nodeBackgroundTileA.anchorPoint = CGPointMake(0, 0);
nodeBackgroundTileA.position = CGPointMake((i * rectWindow.size.height),0);
nodeBackgroundTileA.zPosition = 1;
nodeBackgroundTileA.alpha = 1.0f;
SKSpriteNode *nodeBackgroundTileB = [SKSpriteNode spriteNodeWithTexture:backgroundTextureB size:CGSizeMake(rectWindow.size.height, rectWindow.size.height)];
nodeBackgroundTileB.name = [NSString stringWithFormat:@"BackgroundB_%i", intCurrentBackground];
nodeBackgroundTileB.scene.scaleMode = SKSceneScaleModeAspectFill;
nodeBackgroundTileB.anchorPoint = CGPointMake(0, 0);
nodeBackgroundTileB.position = CGPointMake((i * rectWindow.size.height),0);
nodeBackgroundTileB.zPosition = 1;
nodeBackgroundTileB.alpha = 1.0f;
[backgroundA addChild:nodeBackgroundTileA];
[backgroundB addChild:nodeBackgroundTileB];
DLog(@"Add Background:%i, %@", i, NSStringFromCGPoint(backgroundA.position));
}
SKAction *fadeIn = [SKAction fadeInWithDuration:2.0];
SKAction *fadeOut = [SKAction fadeOutWithDuration:2.0];
SKAction *wait = [SKAction waitForDuration:.6];
SKAction *sequence = [SKAction sequence:@[fadeIn, wait, fadeOut, wait]];
SKAction *repeat = [SKAction repeatActionForever:sequence];
[backgroundB runAction:repeat withKey:@"fade"];
[self addChild:backgroundA];
[self addChild:backgroundB];
}