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

时间:2015-04-20 07:31:11

标签: ios objective-c iphone ipad sprite-kit

我对SKNodes(iOS 8 +)中Sprite Kit通用游戏资产绝对定位有疑问。

我将通过以下示例尝试提出我的问题

想象一下 2D自上而下的游戏,其中SKSpriteNode代表一所房子。房子有多个孩子SKSpriteNode,代表椅子,桌子,沙发等。

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

  • 1x - 200 x 200px(非视网膜iPad),
  • 2x - 400 x 400px(Retina iPhone和iPad),
  • 3x - 600 x 600px(iPhone 6 Plus)。

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

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

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

问题

问题是200x200px400x400px资产通过小型设备,以便在所有设备上实现类似的外观。

问题

  

如何以能够启用的方式成功呈现/导入资产   我要达到类似(如果不是相同)的外观和感觉   设备/屏幕尺寸没有打破子节点定位?

我的需要:

取1

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

选择2

我还可以在分别为iPad设备使用普通SKScene200x200px大小的资源时缩放400x400px尺寸(缩放效果)。这样可以保持子节点的定位工作,但场景/资产的渲染质量不是很好。此外,这感觉就像一个黑客,我们不想要那样。

选3

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

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

感谢您抽出宝贵时间阅读问题!

4 个答案:

答案 0 :(得分:6)

  

我可以在Non-retina iPad上使用现有的400x400px资产   用于房屋节点的Retina iPad设备上的设备和600x600px资产   但是子节点的定位会破裂。这是   因为孩子的位置值不会改变,而且仍然会改变   {20,20}和{40,40}分别用于iPad设备,而资产   会更大。这会产生相对不准确的儿童职位   到房子节点。

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

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

您可以使用两个节点。用于保存"实际"的根节点位置,然后是用于显示图像的图像节点子节点。这样您就可以将位置数据与显示的数据分开。您可以根据需要调整子映像节点的大小和位置,而不会弄乱根节点的实际位置。您甚至可以在JSON中包含这个额外的图像节点数据。

  

我还可以在使用时缩放SKScene尺寸(缩放效果)   iPad设备的正常200x200px和400x400px大小的资产   分别。这有效,它可以保持子节点的定位   工作但场景/资产的渲染质量并不好   应该。此外,这感觉就像一个黑客,我们不想要那样。

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

  

我还可以使用两倍于iPad设备的大资产,并将其翻倍   子节点在运行时的位置。在这种情况下,我会使用一个   非视网膜iPad设备的400x400px资产和新的800x800px资产   用于视网膜iPad设备。虽然这看起来很棒并且让孩子保持健康   节点定位工作,似乎是一个非常大的黑客修复   运行时的子节点位置:

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

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

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

https://stackoverflow.com/a/25256339/2158465

https://stackoverflow.com/a/29171224/2158465

祝你好运,如果你有任何问题,请告诉我。

答案 1 :(得分:2)

没有简单的方法可以做你想做的事。一种方法是在您的设备上使用固定的屏幕尺寸。 iPhone 5的iPhone 5一直使用16:9宽高比的屏幕。 iPad和iPhone 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+屏幕如何,了解确切的屏幕尺寸都可以让您以更精确的方式放置物体。

答案 2 :(得分:0)

使用图片资源,您还可以指定图片的iPad版本。

然而,实际上并没有办法为您的应用添加额外的逻辑,根据您是否在iPad上运行以及手动调整位置进行分支。

我们可以讨论如何最好地融入它:我不喜欢这个“如果我不是这个设备”在整个代码中检查所有内容。创建一个抽象超类和两个子类,每个子类处理一个接口习语的布局(或者你可能想要调用它的任何东西)。你将只需要检查一次(当实例化这些时)和多态性将处理其余的事情。

答案 3 :(得分:0)

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

您所要做的就是为每个设备定义frame'尺寸。