尽管阅读了Apple的大部分文档,并通过他们的论坛阅读并观看了他们的WWDC视频,但我似乎错过了利用纹理打包和Sprite Kit的性能来制作许多大型精灵所需的步骤。
想象100个不同的精灵图像,100个不同的精灵。如果每个图像是256x256像素,则它们将在2048x2048处占用多个SpriteSheet。让我们想象一下这是极限,而不是4096x4096,只是因此可以理解需要不止一个spritesheet。
在任何给定时间,屏幕上可能有多达20个不同的精灵。所以表现是一个考虑因素。
如何导入这些图像,然后以SpriteKit打算在游戏中使用的纹理打包和性能考虑的方式创建这些精灵?
只是指向Apple推荐的绝对步骤的特定链接就可以了。我一定是刚刚掠过它。
完全无法传达:
答案 0 :(得分:1)
那么让我看看我是否可以合理地回答你的问题。请记住,虽然我使用过SpriteKit,但我并不是它的忠实粉丝。当我使用它时,我没有使用Apple提供的任何工具(例如。SKTextureAtlas
,sks
文件等)。尽管如此,这应该仍然适用。按照Apple的最佳做法?我不知道。
问题:导入文件夹或图片?
如果您使用Xcode生成地图集的方式,则Add Files...
为您的项目指定一个名为XYZ.atlas
的文件夹,其中XYZ
将是纹理名称。此文件夹包含将在地图集中的所有纹理。
问题:导入项目中的WHERE?
只需要在你的项目中。但是,您的项目文件中应该有一些组织Group
层次结构。
问题:加载并引用它们,怎么做?
装载的一个例子是(是的,我知道嘘,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
文件夹的屏幕截图。它还显示了一些工具生成的atlas文件。
所以在这里你可以看到我有两个组,它们是文件夹MyTexture.atlas和ProgressBar.atlas的引用。在游戏中,它们将被称为MyTexture
和ProgressBar
。
我还包括了一个相同的地图集,但是预先构建了。 你不会在你的项目中同时拥有它们,我只用它来展示包含预制内容的东西。我使用TexturePacker生成它们。我将在后面讨论为什么这可能是一个更好的选择。 TexturePacker也可以创建SpriteKit地图集而不是地图集PNG。
实际上,地图集实际上只是一个纹理,子纹理与它相关联。子纹理是纹理的X / Y / W / H部分。纹理的实际内存是"保持"由地图集。了解地图集是一个有用的东西,因为如果你必须自己实现它,它可以让你思考如何支持它。或者加强它。
现在让我们来看看如何完全使用它来做一些有用的事情。为此你需要一个纹理管理器(又名TextureManager
),sprite manager(aka { {1}})以及某种表现形式。
清单实际上是" sprite name"之间的某种形式的关联。 to atlas:子纹理对。例如:
SpriteManager
在这种情况下,它是一些JSON,但您可以拥有任何您想要的格式。当我构建我的游戏时,我有一个构建资产阶段,它会生成我的所有纹理,然后构建一个清单。这个清单告诉我不仅存在什么纹理,而且稍后用于找到"精灵名称"的正确关联。到实际的图集和子纹理。 "精灵名称"只是你有一些相关意义的名字。它可能是" zombie"例如。
使用 {
"progressbar": {
"atlas": "ProgressBar",
"subtexture": progressbarbacking"
},
"progressbarfillr": {
"atlas": "ProgressBar",
"subtexture": progressbarfillr"
}
}
作为异步加载器。此外,它是您所有纹理的库存管理器。作为库存管理器,它会阻止您双重加载纹理,并在请求时(如果存在)为您提供纹理/地图集的正确引用。
您可以使用TextureManager
使用清单中的数据创建新的SpriteManager
。例如:
SKSpriteNode
我在这里做了一个单身人士。使用您想要的任何实现。如果你讨厌单身,那很好,这只是一个例子。您会注意到它返回SKSpriteNode *progressBar = [[SpriteManager sharedInstance] createSprite:@"progressbar"];
。我看到很多人从SKSpriteNode
创建子类。我从来没有这样做过。对我来说,图形组件始终是"有一个"。但是,如果你正在做一个"是一个",你仍然可以这样做。你只需要提供你需要的课程。我正在考虑处理这个问题超出范围的方式。
现在,如果您查看清单,您会注意到SKSpriteNode
与名为progressbar
的地图集和名为ProgressBar
的子纹理相关联。为了获得您需要的纹理,您在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];
你有它。一种从地图集中获取精灵的方法。
按照Apple的最佳做法?不知道,但这与我所做的一致。
有些人会抱怨会涉及到词典,其中一些会慢慢来#34;是的,这是一个惩罚。而现实中,我也没有使用字典,但更容易将这个想法作为字典。另外请记住,我认为在加载阶段会出现这种情况,而在游戏过程中则很少,如果有的话。高性能游戏的技巧之一是在实际游戏之前预先加载所需或全部数据。
哦,为什么我预先制作地图集。所以你的问题的一部分是纹理到地图集的组织。这就是原因。我喜欢看生成的地图集并了解尺寸是什么以及尺寸是什么。此外,它使下载的地图集更容易。
作为优化,您可能希望尝试将纹理放在相对相同的时间。例如,将所有HUD项目放在相同的图集中与将HUD与背景混合是有意义的。