尽管阅读了许多Apple文档,阅读了他们的论坛并观看了WWDC视频,但我似乎仍然错过了利用纹理包装和Sprite Kit的性能来制作许多大型Sprite所需的步骤。
想象一下100个不同精灵的100个不同精灵图像。如果每个图像都是256x256像素,则它们将在2048x2048处占用一个以上的SpriteSheet。并假设这是限制,而不是4096x4096,这是因为可以理解,将需要多个spritesheet。
在任何给定时间,屏幕上可能有多达20个不同的精灵。因此,性能是一个考虑因素。
如何导入这些图像,然后以SpriteKit打算用于纹理包装和游戏使用性能考虑的方式创建这些精灵?
只是指向Apple建议的绝对步骤的特定链接就可以了。我一定只是略读了一下。
苹果的新文档走了这么远:
完全无法传达以下内容:
最佳答案
因此,让我看看我是否可以合理地回答您的问题。请记住,虽然我使用过SpriteKit,但我并不喜欢它。当我使用它时,我没有使用Apple提供的任何工具(例如SKTextureAtlas
,sks
文件等)。尽管如此,这仍然应该适用。根据Apple的最佳做法?我不知道。
问题:导入文件夹还是图像?
如果使用Xcode生成 map 集的方法,则将Add Files...
命名为XYZ.atlas
文件夹到项目中,其中XYZ
将是纹理名称。此文件夹包含将在 map 集中的所有纹理。
问题:在项目内导入到哪里?
只是必须在您的项目中。但是,您的项目文件中应该具有一些组织Group
层次结构。
问题:加载并引用它们,如何?
加载示例如下(是的,我知道boo,Obj-C):
self.myTextureAtlas = [SKTextureAtlas atlasNamed:@"MyTexture"];
不可避免地,您将需要访问实际的纹理,并且需要执行以下操作:
self.tex0 = [self.myTextureAtlas textureNamed:@"tex0"];
一个很好的教程在这里:https://www.raywenderlich.com/45152/sprite-kit-tutorial-animations-and-texture-atlases
这也是显示
.atlas
文件夹的屏幕截图。它还显示了一些工具生成的 map 集文件。因此,在这里您可以看到“我有两个组”,它们是对文件夹MyTexture.atlas和ProgressBar.atlas的引用。在游戏中,它们将被称为
MyTexture
和ProgressBar
。作为示例,我还包括了相同的 map 集,但是是预先构建的。您不会在项目中同时拥有这两种功能,我只是用它来显示包括预构建在内的所有内容。我使用TexturePacker生成了它们。稍后我将介绍为什么这可能是一个更好的选择。 TexturePacker还可以创建SpriteKit map 集而不是Atlas PNG。
实际上,图集实际上只是与子纹理相关联的纹理。子纹理是纹理的X / Y / W / H部分。图集“保留”纹理的实际内存。了解 map 集是一件有用的事情,因为它使您可以仔细考虑如果必须自己实施,将如何支持它。或增强它。
现在让我们讨论一下如何使用它来做一些有用的事情,为此,您将需要一个纹理管理器(aka
TextureManager
),精灵管理器(aka SpriteManager
)和某种清单。清单实际上是“精灵名称”与atlas:sub纹理对之间的某种关联形式。例如:
{
"progressbar": {
"atlas": "ProgressBar",
"subtexture": progressbarbacking"
},
"progressbarfillr": {
"atlas": "ProgressBar",
"subtexture": progressbarfillr"
}
}
在这种情况下,它是一些JSON,但是您可以具有所需的任何格式。在构建游戏时,我会拥有一个构建资产阶段,该阶段会生成我的所有纹理,并从中构建清单。该清单不仅告诉我存在哪些纹理,而且以后还用于查找“精灵名称”与实际图集和子纹理的正确关联。 “精灵名称”只是您具有相关含义的一些名称。例如,可能是“僵尸”。
您将
TextureManager
用作异步加载程序。此外,它是您所有纹理的库存管理器。作为库存经理,它将防止您重复加载纹理,并在请求时(如果存在)为您提供对纹理/图集的正确引用。您将使用
SpriteManager
使用清单中的数据来创建新的SKSpriteNode
。例如:SKSpriteNode *progressBar = [[SpriteManager sharedInstance] createSprite:@"progressbar"];
在这里,我使它成为一个单例。使用所需的任何实现。如果您讨厌单身人士,那很好,这只是一个例子。您会注意到,它返回
SKSpriteNode
。我看到很多人从SKSpriteNode
制作子类。我从不这样做。对我而言,图形组件始终是“具有”。但是,如果您正在执行“是”,则仍然可以执行此操作。您只需要提供所需的 class 即可。我正在考虑解决此问题的方法。现在,如果您查看清单,您会注意到
progressbar
与名为ProgressBar
的 map 集和名为progressbarbacking
的子纹理相关联。为了获得所需的纹理,您需要在SpriteManager
中添加一些实现代码,例如:// NOTE the literal names would be variables which contained the unpacked association from progressbar
// literal strings are used to make the idea easier to follow
SKTextureAtlas *atlas = [[TextureMaanger sharedInstance] findAtlasNamed:@"ProgressBar"];
//Error check of course
SKTexture *tex = [atlas textureNamed:@"progressbarbacking"];
// Error check of course
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tex];
也许您只是打个电话:
SKTexture *tex = [[TextureManager] sharedInstance] texNamed:@"progressbarbacking" atlas:@"ProgressBar"];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:tex];
那里有。从 map 集中获取子画面的方法。
根据Apple的最佳做法?邓诺(Dunno),但这是我所做的事情。
有些人会抱怨涉及字典,其中一些会“缓慢”。是的,对此有处罚。实际上,我也没有为此使用字典,但是将其作为字典更容易理解。另外请记住,我认为这种用法发生在加载阶段,而很少发生在游戏过程中(如果有的话)。性能游戏的诀窍之一是在实际游戏之前预加载您需要的全部或尽可能多的数据。
哦,为什么要我预先建立 map 集。因此,您的问题的一部分是组织图集的纹理。这就是为什么。我喜欢看生成的图集,并了解它的大小和内容。此外,它使可下载的 map 集更加容易。
作为一种优化,您将希望尝试放置所有相对同时绘制的纹理。例如,将所有HUD项目都放在同一图集中,而不是将HUD与背景混合在一起,这是有意义的。
关于ios - 导入和创建许多大型 Sprite 的正确方法:SpriteKit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39881364/