通用 2D 游戏资产和绝对节点定位

Universal 2D Game Assets and Absolute Node Positioning

我有一个关于通用游戏资产绝对定位 SKNodes in Sprite Kit的问题( iOS 8+).

我将尝试通过以下示例来展示我的问题:

想象一个 2D top down 游戏,其中 SKSpriteNode 代表一座房子。一个房子有多个 child SKSpriteNode 代表椅子,书桌,沙发等

我有 3 个版本的房屋资产:

重要: Child 节点(椅子、桌子等)位置在 .plist 文件 中定义。像这样(JSON 表示):

children: [
    {
        position = {20,20};
    },
    ...
]

由于位置是以点而不是像素为单位定义的,因此所有内容都会根据设备屏幕比例按预期定位。对于 1x 设备,位置保持 {20,20},对于 2x,位置为 {40,40},对于 3x,位置为 {60,60}

问题:

问题是 200x200px400x400px 资产 对于 iPad 设备 来说太小了,以实现相似的外观和感觉在所有设备上。

问题:

How to successfully present/import assets in a way that would enable me to achieve similar (if not the same) look and feel on all devices/screen sizes without breaking child nodes positioning?

我的作品:

取1:

我可以简单地使用 Non-retina iPad 设备上的现有 400x400px 资产和 Retina iPad 设备上的 600x600px 资产作为 house 节点,但是child 节点的定位会被破坏。这是因为 child 位置值不会改变,对于 iPad 设备仍然是 {20,20}{40,40},而资产会更大。这将产生不准确的 child 相对于房屋节点的位置。

取2:

我还可以缩放 SKScene 大小(缩放效果),同时分别为 iPad 设备使用正常 200x200px400x400px 大小的资产。这有效,它使 child 节点定位工作正常,但 scene/assets 的渲染质量不如应有的好。此外,这感觉像是一个 hack,我们不希望那样。

取3:

我还可以为 iPad 设备使用两倍大的资产,并在运行时将 child 节点位置加倍。在这种情况下,我将为 non-retina iPad 设备使用 400x400px 资产,为视网膜 iPad 设备使用新的 800x800px 资产。虽然这看起来不错并且保持 child 节点定位工作,但它似乎是一个非常大的 hack 在运行时修复 child 节点位置:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    position.x *= 2.0f;
    position.y *= 2.0f;
}

感谢您抽空阅读问题!

使用图像资产,您还可以指定图像的 iPad 个版本。

然而,没有真正的方法可以向您的应用程序添加一些额外的逻辑,根据您的 运行 是否在 iPad 上进行分支,并手动调整位置。

不过,我们可以讨论如何最好地整合它:我不喜欢在整个代码中进行 "if I'm not this device" 检查。创建一个抽象超类和两个子类,每个子类处理一个界面习惯用法的布局(或任何你想称呼它的东西)。您将只需要检查一次(在实例化这些时),多态性将处理其余部分。

I could simply use the existing 400x400px assets on Non-retina iPad devices and 600x600px assets on Retina iPad devices for the house node but the positioning of a child nodes would become broken. This is because the child position value wouldn't change and would still be {20,20} and {40,40} for iPad devices respectively, while the assets would be bigger. This would yield inaccurate child positions relative to the house node.

您可以简单地将房屋节点(不是场景)缩放到更大的尺寸。您需要做的就是将您房子的比例设置为在更大的设备上看起来不错的值。事实上,不用检查 iPad,我们可以想出一个根据屏幕大小设置比例的公式。类似下面的代码应该可以工作。请注意,它假定您的房子完全位于 iPhone 4 上,并且它会始终缩放到所有更大的屏幕。请注意,您确实可以选择任意尺寸作为基本情况,但选择最小的屏幕并按比例放大是最简单的。请务必提供更大的纹理,以便纹理在缩放时不会变得模糊。

[house setScale:self.scene.size.width/320.0];

您可以使用两个节点。一个根节点用于保存 "actual" 位置,然后是一个图像节点子节点用于显示图像。这将允许您将位置数据与显示的内容分开。您可以根据需要调整子图像节点的大小和位置,而不会弄乱根节点的实际位置。您甚至可以在 JSON.

中包含这个额外的图像节点数据

I could also scale the SKScene size (zoom effect) while using the normal 200x200px and 400x400px sized assets for iPad devices respectively. This works and it keeps the child nodes positioning working but the rendered quality of the scene/assets is not good as it should be. Also, this feels like a hack and we don't want that.

如果您的应用程序能够以某种方式处理不同的宽高比,则此选项绝对有效。例如,如果场景的缩放比例大于设备屏幕,您可以允许滚动场景。发生质量损失是因为您将纹理缩放到大于其预期大小。您需要提供更大的纹理以在缩放时保持高质量。在这种情况下,您可能只使用 600x600 图像(或更大)并让它缩放。例如,在我的 OS X 的 RTS Sprite-Kit 游戏中,我缩放了整个场景,以便在所有设备上获得相同的外观。而且我不会损失任何质量,因为我确保提供非常大的纹理,因此在缩放时不会损失质量。


I could also use twice as big assets for iPad devices and double the child nodes position at the runtime. In this case I would use a 400x400px asset for non-retina iPad devices and a new 800x800px asset for retina iPad devices. While this looks great and keeps the child nodes positioning working, it seems like a really big hack fixing child node position during runtime with this:

这也可行,尤其是当您的 iPad 需要自定义布局时。但是,如果可能,请避免专门检查 iPad,而是使用屏幕尺寸来创建布局规则,以便您的节点在所有屏幕尺寸上一致地动态调整(请参阅上面的代码行)。如果您的 iPad 布局与 iPhone 非常不同,有时这是不可能的,在这种情况下您别无选择,只能检查 iPad.


这三个解决方案都很好。我不会考虑其中任何一个 "hacky." 它们都用于不同的目的。您需要找到最适合您的游戏的解决方案。

我还建议您在下面查看我的两个答案。不确定,但它们可以帮助您理解 Sprite Kit 中的通用定位和缩放。

祝你游戏顺利,如有任何问题,请告诉我。

您可以使用 PaintCode 之类的软件来动态生成大小完全符合您需要的纹理。

您只需为每个设备定义 frame' 尺寸。

没有简单的方法可以做您想做的事。一种方法是在您的设备上使用固定的屏幕尺寸。 iPhone 5 一直到 iPhone 6+ 都使用 16:9 屏幕宽高比。而 iPad 和 iPhones 4s 及更早版本,都使用 4:3 屏幕纵横比。

在展示您的 GameScene 之前,您可以确定屏幕的纵横比,然后像这样为 16:9:

设置固定的视图大小
GameScene *startGame = [[GameScene alloc] initWithSize:CGSizeMake(736, 414)];
startGame.scaleMode = SKSceneScaleModeAspectFit;

或者这个 4:3

GameScene *startGame = [[GameScene alloc] initWithSize:CGSizeMake(1024, 768)];
startGame.scaleMode = SKSceneScaleModeAspectFit;

确切的值并不重要,重要的是比率。

无论 iPhone 5 屏还是 6+ 屏,了解确切的屏幕尺寸将使您能够更精确地放置对象。