在SpriteKit中处理不同的iOS设备分辨率

时间:2023-01-22 23:22:10

I'm playing around with SpriteKit in Xcode 6, iOS 8 beta 5. Everything is all laid out and working perfectly on the iPhone 4S simulator, however when switching to the 5S, the elements at the bottom of the screen are cut off.

我在玩Xcode 6 iOS 8 beta 5中的SpriteKit。在iPhone 4S的模拟器上,一切都布置得井井有条,运行得非常完美。然而,当切换到5S时,屏幕底部的元素被切断了。

It was to my understanding that the bottom left corner of the iPhone screen should be CGPoint(0, 0) but after checking the location by printing the coordinates to the console that the lowest point of the left corner I could click was around (5, 44). Is there something wrong in my scene setup thats causing this?

根据我的理解,iPhone屏幕的左下角应该是CGPoint(0,0),但是在检查位置之后,我将坐标打印到控制台,我可以点击的左下角应该是(5,44)左右。我的场景设置有问题吗?

No changes have been made to the GameViewController file and even after I strip the GameScene file the problem persists.

对GameViewController文件没有做任何更改,甚至在我删除GameScene文件之后,问题仍然存在。

Can anyone at least point me in the right direction with this?

至少有谁能告诉我正确的方向吗?

3 个解决方案

#1


108  

Adding the following code will fix your problem (code is in Swift):

添加以下代码将修复您的问题(代码在Swift中):

scene.scaleMode = SKSceneScaleMode.ResizeFill

Now if you want to know why this fixes your problem, what your problem actually is, and how to handle multiple resolutions – I suggest you continue reading.

如果你想知道为什么这能解决你的问题,你的问题到底是什么,以及如何处理多重决心——我建议你继续读下去。

There are three things that can impact the position of nodes in your scene.

有三件事可以影响场景中节点的位置。

1) Anchor Point
Make sure your scene's anchor point is set to (0,0) bottom left. By default the scene's anchor point starts at (0,0) so i'm assuming that is not causing the issue.

1)锚点(Anchor Point)确保场景的锚点设置为(0,0)bottom left。默认情况下,场景的锚点从(0,0)开始,所以我假设这不会引起问题。

2) Size
Check the size of your scene. I typically make my scene size match the size of the device (i.e. iPad, iPhone 4-inch, iPhone 3.5 inch), then I place another layer in the scene for storing my nodes. This makes me able to do a scrolling effect for devices with smaller resolutions, but it depends on your game of-course. My guess is that your scene size might be set to 320, 480 which could be causing the positioning problems on your iPhone 5s.

2)尺寸检查场景的大小。我通常会让我的场景大小与设备的大小相匹配(比如iPad, iPhone 4英寸,iPhone 3.5英寸),然后我在场景中放置另一层来存储我的节点。这使我能够对分辨率较小的设备执行滚动效果,但这取决于您的游戏。我猜你的场景尺寸可能会被设置为320,480,这可能会导致iPhone 5s的定位问题。

3) Scale Mode
The scale mode has a huge effect on the positioning of nodes in your scene. Make sure you set the scale mode to something that makes sense for your game. The scale mode kicks in when your scene size does not match the size of the view. So the purpose of the scale mode is to let Sprite Kit know how to deal with this situation. My guess is that you have the scene size set to 320,480 and the scene is being scaled to match the iPhone 5 view which will cause positioning problems identical to what you described. Below are the various scale modes you can set for your scene.

比例模式比例模式对场景中节点的定位有着巨大的影响。确保你把比例模式设置成对你的游戏有意义的。当您的场景大小与视图的大小不匹配时,缩放模式就会启动。所以比例模式的目的是让Sprite Kit知道如何处理这种情况。我的猜测是,你的场景大小设置为320,480,并且场景正在缩放以匹配iPhone 5的视图,这将导致与你描述的相同的定位问题。下面是您可以为场景设置的各种规模模式。

SKSceneScaleMode.AspectFill

The scaling factor of each dimension is calculated and the larger of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire area of the view is filled, but may cause parts of the scene to be cropped.

计算各维度的比例因子,选择两个维度中较大的一个。场景的每个轴都用相同的比例因子进行缩放。这保证了视图的整个区域被填充,但是可能导致场景的部分被裁剪。


SKSceneScaleMode.AspectFit

The scaling factor of each dimension is calculated and the smaller of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire scene is visible, but may require letterboxing in the view.

计算各维度的比例因子,选择两个维度中较小的一个。场景的每个轴都用相同的比例因子进行缩放。这保证了整个场景是可见的,但是可能需要在视图中使用字母装箱。


SKSceneScaleMode.Fill

Each axis of the scene is scaled independently so that each axis in the scene exactly maps to the length of that axis in the view.

场景的每个轴都是独立缩放的,因此场景中的每个轴都与视图中这个轴的长度成正比。


SKSceneScaleMode.ResizeFill

The scene is not scaled to match the view. Instead, the scene is automatically resized so that its dimensions always matches those of the view.

场景没有按比例缩放以匹配视图。相反,场景会自动调整大小,以便其大小始终与视图的大小相匹配。


Conclusion
It looks like you want to remove the scaling of your scene, that way your positions in the scene will match the actual positions in the view. You can either set your scene's size to match the view size, in which case no scaling will take place. Or you can set your scene's scale mode to ResizeFill which will always make the scene's size match your view's size and it won't scale anything. In general I would stay away from any scaling and instead adjust the interface and the scene size to best suit each device. You may also want to add zoom and/or scrolling to allow devices with smaller resolutions to achieve the same view field.

结论看起来你想要去掉场景的缩放比例,这样你在场景中的位置就会与视图中的实际位置匹配。您可以设置场景的大小以匹配视图的大小,在这种情况下不会发生缩放。或者你可以将场景的缩放模式设置为ResizeFill,这将使场景的大小与视图的大小匹配,它不会缩放任何东西。通常我会远离任何缩放,而是调整界面和场景大小,以最适合每个设备。您可能还需要添加缩放和/或滚动,以允许分辨率较小的设备实现相同的视图字段。


But what if I want to scale my scene?
If however you need to scale your scene, but you still want positions to be relative to the view (i.e. You want (0,0) to be the bottom left of screen even when scene is cutoff) then see my answer here

但是如果我想放大我的场景呢?如果你需要缩放你的场景,但是你仍然想要相对于视图的位置(例如,你想(0,0)是屏幕的左下角,即使场景是截止的),然后在这里看到我的答案


Additional Info
See answer here for sample code showing how I layout nodes dynamically.

有关示例代码的更多信息,请参见这里的答案,该示例代码展示了如何动态布局节点。

See answer here for more details about scaling to support multiple devices.

有关扩展以支持多个设备的详细信息,请参阅这里的答案。

#2


2  

If you want to preserve the size of your scene (usually desired when you work with a fixed size and coordinates system), you might want to add padding to either side of your scene. This would remove the letter boxing and preserve all the physics and dynamics of your app on any platform.

如果您希望保留场景的大小(通常在使用固定大小和坐标系统时需要),您可能希望在场景的任何一边添加填充。这将删除字母装箱,并在任何平台上保存应用程序的所有物理和动态。

I created a small Framework to help with this:

我创建了一个小框架来帮助这一点:

https://github.com/Tokuriku/tokuriku-framework-stash

https://github.com/Tokuriku/tokuriku-framework-stash

Just:

只是:

  1. Download the ZIP file for the Repository
  2. 下载存储库的ZIP文件
  3. Open the "SceneSizer" sub-folder
  4. 打开“SceneSizer”子文件夹
  5. Drag the SceneSizer.framework "lego block" in your project
  6. 在项目中拖拽SceneSizer.framework“lego block”
  7. Make sure that the Framework in Embedded and not just Linked
  8. 确保框架是嵌入的,而不仅仅是链接
  9. Import the Framework somewhere in your code import SceneSizer
  10. 将框架导入到代码导入SceneSizer中。

And you're done, you can now call the sizer Class with: SceneSizer.calculateSceneSize(#initialSize: CGSize, desiredWidth: CGFloat, desiredHeight: CGFloat) -> CGSize

你做完了,现在可以调用sizer类:SceneSizer。calculatescenze (#initialSize: CGSize, desiredWidth: CGFloat, desiredHeight: CGFloat) -> CGSize

#3


0  

Just in case, try doing CMD+1, worked for me. Some of the elements were cut off because they were simply not displayed in Simulator - I stress this, this is just a simulator feature (and a bug if you ask me, wasted hours of time to solve this). CMD+2, CMD+3 views can sometimes hide parts of the scene.

以防万一,试试CMD+1,为我工作。一些元素被切断了,因为它们根本不在模拟器中显示——我强调,这只是一个模拟器特性(如果你问我,这是一个错误,浪费了很多时间来解决这个问题)。CMD+2, CMD+3视图有时可以隐藏场景的部分。

#1


108  

Adding the following code will fix your problem (code is in Swift):

添加以下代码将修复您的问题(代码在Swift中):

scene.scaleMode = SKSceneScaleMode.ResizeFill

Now if you want to know why this fixes your problem, what your problem actually is, and how to handle multiple resolutions – I suggest you continue reading.

如果你想知道为什么这能解决你的问题,你的问题到底是什么,以及如何处理多重决心——我建议你继续读下去。

There are three things that can impact the position of nodes in your scene.

有三件事可以影响场景中节点的位置。

1) Anchor Point
Make sure your scene's anchor point is set to (0,0) bottom left. By default the scene's anchor point starts at (0,0) so i'm assuming that is not causing the issue.

1)锚点(Anchor Point)确保场景的锚点设置为(0,0)bottom left。默认情况下,场景的锚点从(0,0)开始,所以我假设这不会引起问题。

2) Size
Check the size of your scene. I typically make my scene size match the size of the device (i.e. iPad, iPhone 4-inch, iPhone 3.5 inch), then I place another layer in the scene for storing my nodes. This makes me able to do a scrolling effect for devices with smaller resolutions, but it depends on your game of-course. My guess is that your scene size might be set to 320, 480 which could be causing the positioning problems on your iPhone 5s.

2)尺寸检查场景的大小。我通常会让我的场景大小与设备的大小相匹配(比如iPad, iPhone 4英寸,iPhone 3.5英寸),然后我在场景中放置另一层来存储我的节点。这使我能够对分辨率较小的设备执行滚动效果,但这取决于您的游戏。我猜你的场景尺寸可能会被设置为320,480,这可能会导致iPhone 5s的定位问题。

3) Scale Mode
The scale mode has a huge effect on the positioning of nodes in your scene. Make sure you set the scale mode to something that makes sense for your game. The scale mode kicks in when your scene size does not match the size of the view. So the purpose of the scale mode is to let Sprite Kit know how to deal with this situation. My guess is that you have the scene size set to 320,480 and the scene is being scaled to match the iPhone 5 view which will cause positioning problems identical to what you described. Below are the various scale modes you can set for your scene.

比例模式比例模式对场景中节点的定位有着巨大的影响。确保你把比例模式设置成对你的游戏有意义的。当您的场景大小与视图的大小不匹配时,缩放模式就会启动。所以比例模式的目的是让Sprite Kit知道如何处理这种情况。我的猜测是,你的场景大小设置为320,480,并且场景正在缩放以匹配iPhone 5的视图,这将导致与你描述的相同的定位问题。下面是您可以为场景设置的各种规模模式。

SKSceneScaleMode.AspectFill

The scaling factor of each dimension is calculated and the larger of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire area of the view is filled, but may cause parts of the scene to be cropped.

计算各维度的比例因子,选择两个维度中较大的一个。场景的每个轴都用相同的比例因子进行缩放。这保证了视图的整个区域被填充,但是可能导致场景的部分被裁剪。


SKSceneScaleMode.AspectFit

The scaling factor of each dimension is calculated and the smaller of the two is chosen. Each axis of the scene is scaled by the same scaling factor. This guarantees that the entire scene is visible, but may require letterboxing in the view.

计算各维度的比例因子,选择两个维度中较小的一个。场景的每个轴都用相同的比例因子进行缩放。这保证了整个场景是可见的,但是可能需要在视图中使用字母装箱。


SKSceneScaleMode.Fill

Each axis of the scene is scaled independently so that each axis in the scene exactly maps to the length of that axis in the view.

场景的每个轴都是独立缩放的,因此场景中的每个轴都与视图中这个轴的长度成正比。


SKSceneScaleMode.ResizeFill

The scene is not scaled to match the view. Instead, the scene is automatically resized so that its dimensions always matches those of the view.

场景没有按比例缩放以匹配视图。相反,场景会自动调整大小,以便其大小始终与视图的大小相匹配。


Conclusion
It looks like you want to remove the scaling of your scene, that way your positions in the scene will match the actual positions in the view. You can either set your scene's size to match the view size, in which case no scaling will take place. Or you can set your scene's scale mode to ResizeFill which will always make the scene's size match your view's size and it won't scale anything. In general I would stay away from any scaling and instead adjust the interface and the scene size to best suit each device. You may also want to add zoom and/or scrolling to allow devices with smaller resolutions to achieve the same view field.

结论看起来你想要去掉场景的缩放比例,这样你在场景中的位置就会与视图中的实际位置匹配。您可以设置场景的大小以匹配视图的大小,在这种情况下不会发生缩放。或者你可以将场景的缩放模式设置为ResizeFill,这将使场景的大小与视图的大小匹配,它不会缩放任何东西。通常我会远离任何缩放,而是调整界面和场景大小,以最适合每个设备。您可能还需要添加缩放和/或滚动,以允许分辨率较小的设备实现相同的视图字段。


But what if I want to scale my scene?
If however you need to scale your scene, but you still want positions to be relative to the view (i.e. You want (0,0) to be the bottom left of screen even when scene is cutoff) then see my answer here

但是如果我想放大我的场景呢?如果你需要缩放你的场景,但是你仍然想要相对于视图的位置(例如,你想(0,0)是屏幕的左下角,即使场景是截止的),然后在这里看到我的答案


Additional Info
See answer here for sample code showing how I layout nodes dynamically.

有关示例代码的更多信息,请参见这里的答案,该示例代码展示了如何动态布局节点。

See answer here for more details about scaling to support multiple devices.

有关扩展以支持多个设备的详细信息,请参阅这里的答案。

#2


2  

If you want to preserve the size of your scene (usually desired when you work with a fixed size and coordinates system), you might want to add padding to either side of your scene. This would remove the letter boxing and preserve all the physics and dynamics of your app on any platform.

如果您希望保留场景的大小(通常在使用固定大小和坐标系统时需要),您可能希望在场景的任何一边添加填充。这将删除字母装箱,并在任何平台上保存应用程序的所有物理和动态。

I created a small Framework to help with this:

我创建了一个小框架来帮助这一点:

https://github.com/Tokuriku/tokuriku-framework-stash

https://github.com/Tokuriku/tokuriku-framework-stash

Just:

只是:

  1. Download the ZIP file for the Repository
  2. 下载存储库的ZIP文件
  3. Open the "SceneSizer" sub-folder
  4. 打开“SceneSizer”子文件夹
  5. Drag the SceneSizer.framework "lego block" in your project
  6. 在项目中拖拽SceneSizer.framework“lego block”
  7. Make sure that the Framework in Embedded and not just Linked
  8. 确保框架是嵌入的,而不仅仅是链接
  9. Import the Framework somewhere in your code import SceneSizer
  10. 将框架导入到代码导入SceneSizer中。

And you're done, you can now call the sizer Class with: SceneSizer.calculateSceneSize(#initialSize: CGSize, desiredWidth: CGFloat, desiredHeight: CGFloat) -> CGSize

你做完了,现在可以调用sizer类:SceneSizer。calculatescenze (#initialSize: CGSize, desiredWidth: CGFloat, desiredHeight: CGFloat) -> CGSize

#3


0  

Just in case, try doing CMD+1, worked for me. Some of the elements were cut off because they were simply not displayed in Simulator - I stress this, this is just a simulator feature (and a bug if you ask me, wasted hours of time to solve this). CMD+2, CMD+3 views can sometimes hide parts of the scene.

以防万一,试试CMD+1,为我工作。一些元素被切断了,因为它们根本不在模拟器中显示——我强调,这只是一个模拟器特性(如果你问我,这是一个错误,浪费了很多时间来解决这个问题)。CMD+2, CMD+3视图有时可以隐藏场景的部分。