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

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

我将尝试通过一个例子来展示我的问题,如下所示

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

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

  • 1x - 200 x 200px (非视网膜iPad),
  • 2x - 400 x 400px (视网膜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资产是适用于iPad的小型设备。

问题

如何成功地呈现/导入资产,使我能够在不破坏子节点定位的情况下,在所有设备/屏幕尺寸上实现类似(如果不是相同的)外观和感觉?

我需要:

以1

我可以简单地使用非视网膜iPad设备上的现有400x400px资源和Retina iPad设备上的600x600px资产作为家庭节点,但是子节点的定位将会被打破。 这是因为孩子的位置值不会改变,分别为iPad设备{20,20}{40,40} ,而资产会更大。 这会产生相对于房屋节点不准确的儿童位置。

以2

我还可以分别在iPad设备上使用普通的200x200px400x400px大小的资源来缩放SKScene大小(缩放效果)。 这个工作,并保持孩子节点定位工作,但现场/资产的渲染质量是不好的,因为它应该是。 此外,这感觉像一个黑客,我们不希望这一点。

以3

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

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

感谢您花时间阅读这个问题!

我可以简单地使用非视网膜iPad设备上的现有400x400px资源和Retina iPad设备上的600x600px资产作为家庭节点,但是子节点的定位将会被打破。 这是因为孩子的位置值不会改变,分别为iPad设备{20,20}和{40,40},而资产会更大。 这会产生相对于房屋节点的不准确的儿童位置。

您可以简单地将您的房屋节点(而不是场景)缩放到更大的尺寸。 所有你需要做的就是把你家的规模设置为在大型设备上看起来不错的价值。 事实上,我们可以不用检查iPad,而是根据屏幕的大小设定一个公式。 像下面的代码应该工作。 请注意,它假定你的房子是完全定位在iPhone 4上,它将一贯地扩展到所有大屏幕。 请注意,你真的可以select任意大小作为你的基本情况,但select最小的屏幕和扩大是最容易的。 只要确保提供更大的纹理,以便在缩放时纹理不会变得模糊。

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

要么

你可以使用两个节点。 保存“实际”位置的根节点,然后是用于显示图像的图像节点子节点。 这将允许您将您的位置数据与正在显示的数据分开。 您可以resize并定位您的子图像节点,但不会影响根节点的实际位置。 你甚至可以在你的JSON中包含这个额外的图像节点数据。


我还可以分别在iPad设备上使用普通的200x200px和400x400px大小的资源来缩放SKScene大小(缩放效果)。 这个工作,并保持孩子节点定位工作,但现场/资产的渲染质量是不好的,因为它应该是。 此外,这感觉像一个黑客,我们不希望这一点。

如果你的应用程序可以处理不同的纵横比,这个选项肯定可以工作。 例如,如果场景缩放比设备屏幕更大,则可以允许滚动场景。 质量的损失发生是因为您正在缩放大于预期大小的纹理。 缩放时,您需要提供更大的纹理以保持高质量。 在这种情况下,您可能只需使用您的600×600图像(或者甚至更大),并使用缩放进行缩放。 例如,在我的RTS Sprite-Kit OS X游戏中,可以扩展整个场景,以便在所有设备上获得相同的外观。 而且我不会失去任何质量,因为我确保提供非常大的纹理,因此缩放时质量不会有任何损失。


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

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


所有这三个解决scheme都很好。 我不会认为他们中的任何一个是“哈克”。 他们都为不同的目的而工作。 您需要find最适合游戏的解决scheme。

我也build议你在下面看到我的两个答案。 不知道,但他们可以帮助您了解Sprite Kit中的通用定位和缩放。

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

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

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

没有简单的方法来做你想要的。 一种方法是在您的设备上使用固定的屏幕尺寸。 iPhone 5一直到iPhone 6+的屏幕都采用16:9的宽高比。 而iPad和iPhone 4以及更早的版本都使用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+屏幕。

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

然而,在你的应用程序中添加一些额外的逻辑并没有真正的方法,取决于你在iPad上运行是否分支,以及手动调整位置。

尽pipe我们可以讨论如何最好地融合:我不是这个“如果我不是这个设备”的粉丝检查整个代码。 创build一个抽象超类和两个子类,每个处理一个接口习惯用法布局(或任何你可能想要调用它)。 你将只需要检查一次(当实例化这些时)和多态性会照顾其余的。

您可以使用PaintCode软件dynamic生成完全按照您的需要大小的纹理。

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