使用SpriteKit高效渲染平铺地图

时间:2015-03-09 20:48:48

标签: cocoa swift opengl sprite-kit

作为练习,我决定在Swift中为OSX编写一个SimCity(原始)克隆。我使用SpriteKit启动了项目,最初将每个tile作为SKSpriteNode的实例,并在该tile更改时交换每个节点的纹理。这导致了糟糕的性能,因此我将绘图切换到常规Cocoa窗口,实现drawRect以在正确的tile位置绘制NSImage s。这个解决方案运行良好,直到我需要实现非常快速刷新的动画图块。

从这里开始,我回到了第一种方法,这次使用纹理图集来减少所需的绘制量,但是,交换需要动画的节点纹理仍然非常慢,并且对其产生了巨大的不利影响。帧率。

我试图显示44x44平铺地图,其中每个平铺是16x16像素。我知道这里必须是一种有效的(或者更正确的方式)来做到这一点。这引出了我的问题:

是否有一种有效的方法来支持SpriteKit中的1500多个节点,并通过更改纹理来动画?更重要的是,我是否采用SpriteKit和SKSpriteNode对地图中的每个图块采取了错误的方法(即使我只重绘脏图)?另一种方法(也许是OpenGL?)会更好吗?

非常感谢任何帮助。我很乐意提供代码示例,但我不确定他们对此问题的相关性/帮助程度。

修改 以下是相关绘图代码和图像的一些链接,以说明问题:

截图: Swiftopolis

当玩家点击小地图时,大地图的中心位置会发生变化。一个事件从小地图发出,中央引擎为游戏提供动力,然后转发给听众。在大地图上执行的代码可以在这里找到所有纹理的变化:

https://github.com/chrisbenincasa/Swiftopolis/blob/drawing-performance/Swiftopolis/GameScene.swift#L489

该代码使用tileImages,它是运行时生成的纹理图集的包装器。

https://github.com/chrisbenincasa/Swiftopolis/blob/drawing-performance/Swiftopolis/TileImages.swift

请原谅代码的混乱 - 我为这次调查设立了一个替代分支,并且没有清理掉过去迭代中遗留下来的大量残留代码。

1 个答案:

答案 0 :(得分:2)

我不知道这是否会“回答”你的问题,但可能有所帮助。

SpriteKit可能能够处理你需要的东西,但你需要查看SpriteKit的不同优化,以及更多的游戏逻辑。

SpriteKit。创建一个.atlas是迄今为止你能做的最好的事情之一,它将有助于保持你的绘制调用。另外,当我学会了很难的方法时,只要你需要它们就保持指向你的SKTextures的指针,并且只生成你需要的那些。例如,每次需要myImage的纹理时,不要创建textureWithImageNamed @“myImage”,而是继续重用纹理并将其存储在字典中。另外skView.ignoresSiblingOrder = YES;帮助了很多,但你必须在所有精灵上管理你自己的zPosition。

游戏逻辑。每个循环更新每个区块将非常昂贵。你会想看一个更好的方法来做到这一点。保留较小的数组或者在后台线程上进行逻辑(模型)更新。

如果你想要调用Old Frank,我目前有一个你可以查看的项目。我有一张75 x 75的地图,32px乘32px的瓷砖可以堆叠2个高。我同时拥有Mac和iOS目标,因此您可以在理论上炸毁场景大小并查看性能如何保持不变。并不是说没有优化工作要做(这是一项正在进行的工作),但我觉得这可能有助于让你至少指出正确的方向。

希望有所帮助。