Can I create a SpriteKit texture atlas at runtime

I am developing an os x / iOS crossword puzzle that uses SKLabelNode to display the letters of the crosswords as a child in an SKNode subclass .

So, for each letter there is an SKNode.SKLabelNode . Without using SKLabelNode, the number of callbacks is in the range 6-8. Using SKLabelNode they increase the number of children in the scene, which can be almost 100.

Now I'm looking for a way to avoid this and have come up with the idea of ​​rasterizing the SKLabelNode to the texture, but this does not reduce the number of calls since there are still many different textures.

My idea is now to rasterize these SKNode -Subclasses and place the textures in the texture atlas.

So the question is, is it possible to create a texture atlas at runtime? What if one texture changes? Is it possible to share one texture in the atlas or is that why I need to rebuild it?

And maybe there is a "better way" to deal with many different SKLabelNodes !?

+3


source to share


2 answers


I would go with a letter class that is a subclass of SKSpriteNode and an atlas called letters. This way you will draw all the letters in one draw pass (100 draws are unnecessary in this situation). Or you don't even need to subclass SKSpriteNode ... You can simply do this:

 SKSpriteNode *letterSprite = [SKSpriteNode spriteNodeWithTexture:[atlas textureNamed:[NSString stringWithFormat:@"%@",character]]];

      

A limitation of this approach is that the letters would have a predefined size. I doubt if you need letters of different sizes in your crossword puzzle game. If you need to resize the letters, you can still scale them, but I think the loss in quality would theoretically come from scaling bitmaps. I am speaking theoretically because in most cases the quality loss is not noticeable.



Here's an example of my TextNode, which parses a given string (numbers in my case) and creates sprites that are drawn in one pass (instead of using SKLabelNode for each individual number). Images in atlases should be named a@2x.png , b@2x.png , or if numbers are 1@2x.png , 2@2x.png , etc.

static const float kCharacterDistance = 6.0f;

#import "TextNode.h"

@interface TextNode()


@property (nonatomic,strong) NSMutableArray* characters;

@end

@implementation TextNode

-(instancetype)initWithPosition:(CGPoint)position andText:(NSString*)text{

    if(self =[super init]){

        self.characters = [[NSMutableArray alloc] initWithCapacity:[text length]];

        SKTextureAtlas *atlas = [SKTextureAtlas atlasNamed:@"numbers"];



        for(NSUInteger i =0; i < [text length];i++){

            NSString *character = [text substringWithRange:NSMakeRange(i, 1)];

            SKSpriteNode *characterSprite = [SKSpriteNode spriteNodeWithTexture:[atlas textureNamed:[NSString stringWithFormat:@"%@",character]]];
            characterSprite.color = [SKColor yellowColor];
            characterSprite.colorBlendFactor = 1.0f;
            characterSprite.position = CGPointMake(i*kCharacterDistance,0);

            [self.characters addObject:characterSprite];

            [self addChild:characterSprite];
        }
   self.position = position;
    }

    return self;
}

@end

      

Hope this helps and gives you a basic idea on how to draw all letters in a single pass. And notice how I color the letters. The texture atlases have white images, but I easily paint them to the desired color.

0


source


As long as your FPS is good, don't worry about anything else. Also, remember that Xcode automatically generates texture atlases at runtime, so you don't have to do anything yourself.



You can set skView.ignoresSiblingOrder = YES;

to improve performance slightly.

0


source







All Articles