我可以在运行时创建 SpriteKit 纹理图集吗
Can I create SpriteKit texture atlas in runtime
我正在开发一个 os x / iOS cros 剑游戏,它使用 SKLabelNode 来显示 crossword 字母作为 child 在 SKNode 子类上。
所以每个字母都有 SKNode.SKLabelNode。不使用 SKLabelNode 绘制计数在 6-8 范围内。使用 SKLabelNode 它们可以达到场景中 children 的数量,可以是 almost 100。
我现在正在寻找一种方法来避免这种情况,并想出了将 SKLabelNode 栅格化为纹理的想法,但这不会降低绘制计数,因为仍然有许多不同的纹理。
我现在的想法是光栅化这些 SKNode-子类并将纹理放入纹理图集中。
那么问题来了,是否可以在运行时创建纹理图集os?如果单个纹理发生变化怎么办? pos是否可以在图集中交换单个纹理,或者我必须重建它?
也许有一个 "best way" 来处理很多不同的 SKLabelNodes!?
我会选择字母 class,它是 SKSpriteNode 的子class 和一个名为字母的图集。这样,您将在单次绘制过程中绘制所有字母(在这种情况下不需要 100 次绘制过程)。或者你甚至不必制作 SKSpriteNode 的子class...你可以这样做:
SKSpriteNode *letterSprite = [SKSpriteNode spriteNodeWithTexture:[atlas textureNamed:[NSString stringWithFormat:@"%@",character]]];
这种方法的局限性在于字母具有预先确定的大小。我怀疑您的填字游戏中是否需要不同大小的字母。如果你需要改变字母的大小,你仍然可以缩放它们,但我猜理论上会因为缩放位图而导致一些质量损失。我说理论上是因为在大多数情况下质量损失并不明显。
这是我的 TextNode 的一个示例,它解析给定的字符串(在我的例子中是数字)并创建单次绘制的精灵(而不是对每个数字都使用 SKLabelNode)。地图集中的图像应命名为 a@2x.png、b@2x.png,或者如果使用数字 1@2x.png、2@2x.png 等
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
希望这对您有所帮助,并让您了解如何在单次绘制过程中绘制所有字母的基本概念。并注意我如何给字母上色。在纹理图集中图像是白色的,但我很容易将它们着色为所需的颜色。
只要你的FPS不错,别的不用担心。另外,请记住 Xcode 会在运行时自动创建纹理图集,因此您不必自己动手。
您可以设置 skView.ignoresSiblingOrder = YES;
来稍微提高您的性能。
我正在开发一个 os x / iOS cros 剑游戏,它使用 SKLabelNode 来显示 crossword 字母作为 child 在 SKNode 子类上。
所以每个字母都有 SKNode.SKLabelNode。不使用 SKLabelNode 绘制计数在 6-8 范围内。使用 SKLabelNode 它们可以达到场景中 children 的数量,可以是 almost 100。
我现在正在寻找一种方法来避免这种情况,并想出了将 SKLabelNode 栅格化为纹理的想法,但这不会降低绘制计数,因为仍然有许多不同的纹理。
我现在的想法是光栅化这些 SKNode-子类并将纹理放入纹理图集中。
那么问题来了,是否可以在运行时创建纹理图集os?如果单个纹理发生变化怎么办? pos是否可以在图集中交换单个纹理,或者我必须重建它?
也许有一个 "best way" 来处理很多不同的 SKLabelNodes!?
我会选择字母 class,它是 SKSpriteNode 的子class 和一个名为字母的图集。这样,您将在单次绘制过程中绘制所有字母(在这种情况下不需要 100 次绘制过程)。或者你甚至不必制作 SKSpriteNode 的子class...你可以这样做:
SKSpriteNode *letterSprite = [SKSpriteNode spriteNodeWithTexture:[atlas textureNamed:[NSString stringWithFormat:@"%@",character]]];
这种方法的局限性在于字母具有预先确定的大小。我怀疑您的填字游戏中是否需要不同大小的字母。如果你需要改变字母的大小,你仍然可以缩放它们,但我猜理论上会因为缩放位图而导致一些质量损失。我说理论上是因为在大多数情况下质量损失并不明显。
这是我的 TextNode 的一个示例,它解析给定的字符串(在我的例子中是数字)并创建单次绘制的精灵(而不是对每个数字都使用 SKLabelNode)。地图集中的图像应命名为 a@2x.png、b@2x.png,或者如果使用数字 1@2x.png、2@2x.png 等
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
希望这对您有所帮助,并让您了解如何在单次绘制过程中绘制所有字母的基本概念。并注意我如何给字母上色。在纹理图集中图像是白色的,但我很容易将它们着色为所需的颜色。
只要你的FPS不错,别的不用担心。另外,请记住 Xcode 会在运行时自动创建纹理图集,因此您不必自己动手。
您可以设置 skView.ignoresSiblingOrder = YES;
来稍微提高您的性能。