0

all. I am now developing an ios game using sprite kit.The game mechanics include: infinitely scroll sprites from top to bottom.

My game scene holds just 3 sprites,top,middle,bottom. I have dozens of sprite images,so my solution is dynamic create 3 sprites ( so the sprites can fill the whole screen),when the bottom sprite is off screen,then destroy it;when the top sprite goes down the top frame,create a new sprite node,then exchange the bottom,middle,top sprite.

The pseudo code: in the interface file:

 - GameScene:SKScene
 {
      ...
      SKSpriteNode *_topSprite;
      SKSpriteNode *_middleSprite;
      SKSpriteNode *_bottomSprite;
      ...
 }

in the implementation file:

- (void)update:(CFTimeInterval)currentTime 
{
   // 1 compute time interval


   // 2 update sprite node
    _topSprite.position move down  100*timeInterval
   _middleSprite.position move down  100*timeInterval  
   _bottomSprite.position move down    100*timeInterval 

   // 3 crop the off-screen bottom sprite node
   if (_bottomSprite is offScreen)
   {
       [_bottomSprite removeFromParent]
   }

   // 4 check the highest sprite position visible
   // if the highest position is below the frame top,then create new sprite
   _bottomSprite = _middleSprite;  
   _middleSprite = _topSprite;
   _topSprite    = [self createNewNode]; // random a sprite image 
}

the game fps is 60,and the nodes counts is not increasing. All seems good,but i found sometimes the game just suddenly has a very shot choke causing the moving frame not continuous. In my instinct,I thought the main reason is caused by step 4. But I don't have any idea to solve it. Any suggestions will be appreciated.

Here is the createNewNode method:

- (SKSpriteNode *)createNewNode {
    NSString *blockName = [self randomImageName];

    SKSpriteNode *sprite = [[SKSpriteNode alloc] initWithImageNamed:blockName];
    sprite.position = _highestPosition;
    sprite.anchorPoint = CGPointMake(0.5, 0);
    NSLog(@"putAnotherNodeOnTop %@", blockName);
    [self addChild:sprite];
    return sprite;
}
cartmanie
  • 3
  • 3
  • What is the size of your sprites images? Are they loaded from sprites.atlas? – Akaino Jul 11 '14 at 11:30
  • My sprite images are all the same size:390*512.I don't use sprites.atlas. – cartmanie Jul 11 '14 at 11:31
  • Weird. There shouldn't be such a problem. Could you post your createNode please? – Akaino Jul 11 '14 at 11:35
  • I paste the code in the post. – cartmanie Jul 11 '14 at 11:45
  • Use Time Profiler to determine which line of code is most expensive – Andrey Gordeev Jul 11 '14 at 12:09
  • 1. Use atlas. 2. Don't release / create new sprites, use the same 3 sprites throughout the game. Just change their position and, if need be, their texture as you move them from bottom to top. #2 is probably where your performance issue comes from since alloc/release cycles for sprites are expensive, more so if they have to load individual images and those images aren't in an atlas, meaning each individual image has to be loaded rather than being able to preload the entire atlas at the beginning. – CodeSmile Jul 11 '14 at 12:12

1 Answers1

0

A couple of suggestions.

Since you are using the same three images, you don't need to re-create the sprites each time. It should be less expensive to set the hidden value to YES, move the sprite somewhere, set the texture and then show it again with hidden to NO. SpriteKit doesn't draw hidden nodes, or ones off screen.

Your code basically asks for a PNG on disk every frame in update when createNewNode: is called. It should be more performant to load the textures in memory and assign them to sprites as needed. If you have just a few, making them SKTexture instance variables would be an easy way to do it.

Use spritesheets (texture atlases), it is much faster to draw an image from memory at mapped coordinates than to load it from disk each time. For example with three images in a spritesheet this can be a single draw call. From disk this is three separate draw calls.

You are returning a sprite and adding it to the scene in the createNewNode: method. Maybe that is what you want for some reason. It stood out as possible duplicate effort.

jgnovak-dev
  • 495
  • 3
  • 11