3
votes

Working on an iOS game using SpriteKit. My background is made up of map tiles (essentially an infinite map, procedurally generated).

Our system is designed to manage "chunks" of the map, and we only load chunks near the player. Since SpriteKit requires we add SKSpriteNodes, we no longer have clean control over "unloading" sprites for chunks/tiles that are no longer near the player.

I realize SpriteKit won't actually render things off-screen, but it's going to kill performance if we can't remove sprites no longer needed, or check if a chunk/tile is already added.

Since SKNodes doesn't respond to isEqual:, I only see two ways to do this:

  • Give each sprite a name with their chunk/tile coordinate, and check this name each update
  • Maintain a separate array of loaded tiles and check that instead

Is there any easier way of checking/removing if a sprite has been added already? Maybe a partial string match on sprite name?

I'm not sure that using SpriteKit is the best solution (Xcode simulator seems to drag at 30fps, have yet to test on a real device). We originally built this game in Java and we're rendering our own textures - hence only what was loaded and could be fed into opengl manually.

-(void) renderToScene:(SKScene *)scene {

    for( Chunk *chunk in loadedChunks ){
        for( Tile *tile in [chunk getTiles] ){

            SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tileTexture];
            sprite.name = @"Tile";
            sprite.position = CGPointMake(realX,realY);
            [scene addChild:sprite];
        }
    }
}
2

2 Answers

6
votes

What will in fact kill your framerate is frequently creating and removing nodes - you should have a pool of sprites that you re-use rather than recreate.

Just update the sprite's texture, position and other attributes when reusing one of those you no longer need. A common use case is to have enough tiles to span the entire screen plus one row and one column, so that when an entire row or column has moved outside the screen you can reposition it at the other side with new textures according to the map data.

0
votes

If i'm understanding what you're asking correctly. You want to properly remove a node/sprite from the scene if its no longer within view.

You should just be able to call the [self removeFromParent] method to remove in whenever its outside the bounds of the screen. Remember you can call this method on any object as long as its a child.

For instance if i had character,

SKSpriteNode *character; SKSpriteNode *sword;

//all the rest of the properties are up to you.

if my character picked up a sword in the game and after a certain time period the sword is no longer accessible. I would do:

[character addChild:sword]; which would add it to the character.

[sword removeFromParent]; when i no longer need the sword to be apart of its parent.