如何在Sprite Kit中设置纹理以平铺

我正在制作一个精灵套件游戏,并且使用平铺纹理的一个大SKSpriteNode比拥有多个具有贴图纹理的SKSpriteNode更有效率。 我的问题是,当我尝试使用5×5瓷砖

SKTexture* tex = [SKTexture textureWithRect:CGRectMake(0,0,5,5) inTexture:[SKTexture textureWithImageNamed:@"tile.png"]]; SKSpriteNode* node = [SKSpriteNode spriteNodeWithTexture:tex size:CGSizeMake(100,100)]; 

图像大小合适,但是被夹住,没有平铺。 在openGL中,我得到一个GL_CLAMP_TO_EDGE,我想要一个GL_REPEAT。 无论如何,我可以在单个SKSpriteNode中实现纹理的拼贴效果,而不会创build非常大的图像。

这是我的问题的一个形象: 在这里输入图像说明

Afaik,没有办法创build平铺纹理的精灵。 但是你可以做什么,在一个绘图过程中渲染很多精灵。

从Apple的文档 (Sprite Kit Best Practices – >绘制您的内容):

如果一个节点的所有子节点都使用相同的混合模式和纹理图集,那么Sprite Kit通常可以在一个绘图通道中绘制这些精灵。 另一方面,如果孩子的组织方式使得每个新的精灵的绘画模式都发生了变化,那么Sprite Kit可能会作为每个精灵的一个绘图过程执行,效率相当低。

创build纹理时应用ciaffinetile滤镜。

 SKTexture* tex = [SKTexture textureWithRect:CGRectMake(0,0,5,5) inTexture:[SKTexture textureWithImageNamed:@"tile.png"]]; 

textureWithRect:inTexture:创build一个子文本,矩形参数在单位坐标空间 ,这意味着所有的值都是0-1

CGRectMake(0,0,5,5)行为是未定义的,但似乎将纹理拉伸了5倍。


编辑 :单位坐标空间

您可以将单位坐标视为指定总可能值的百分比。 单位坐标空间中的每个坐标的范围为0.0到1.0。 例如,沿着x轴,左边缘在坐标0.0处,右边缘在坐标1.0处。 沿着y轴,单位坐标值的方向根据平台而变化

核心animation编程指南,图层使用两种types的坐标系统

为了帮助我转换坐标系,我使用下面的函数 – 这样我可以像上面(5,5)一样使用绝对坐标:

 //Pass the absolute sizes of your sub-texture (subRect) and main-texture (mainRect) CGRect unitCoordinateGivenSubRectInRect (CGRect subRect, CGRect mainRect) { if (mainRect.size.height == 0 || mainRect.size.width == 0) { return CGRectZero; } float x = subRect.origin.x / mainRect.size.width; float y = subRect.origin.y / mainRect.size.height; float sizeX = subRect.size.width / mainRect.size.width; float sizeY = subRect.size.height / mainRect.size.height; return CGRectMake(x, y, sizeX, sizeY); } 

我发现这个问题并不完美。 我这样解决了

你知道你可以通过resizableImageWithCapInsets在UIButton或UIImageView中做到这一点,所以,这是我的解决scheme:

 -(SKTexture *)textureWithImage:(UIImage *)image tiledForSize:(CGSize)size withCapInsets:(UIEdgeInsets)capInsets{ //get resizable image image = [image resizableImageWithCapInsets:capInsets]; //redraw image to target size UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f); [image drawInRect:CGRectMake(0, 0, size.width-1, size.height-1)]; [[UIColor clearColor] setFill]; //get target image UIImage *ResultImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // get texture SKTexture * texture = [SKTexture textureWithImage:ResultImage]; return texture; }