Universal 2D Games and Absolute Node Positioning

I have a question regarding universal gaming assets and the absolute positioning of SKNodes in the Sprite Kit (iOS 8 +).

I will try to present my problem in the following example:

Imagine a top-down 2D game with SKSpriteNode , which is a home. There are many SKSpriteNode children in the SKSpriteNode , which are chairs, a desk, a sofa, etc.

I have 3 versions of home property:

  • 1x - 200 x 200px (Non-Mesh iPads)
  • 2x - 400 x 400px (Retina iPhones and iPads),
  • 3x - 600 x 600px (iPhone 6 Plus).

Attention! : Positions of child nodes (chairs, table, etc.) Defined in the .plist file. Something like this (JSON representation):

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

Since the position is determined in points rather than pixels, everything becomes positioned, as expected, in accordance with the scale of the device’s screen. For 1x devices, the position remains {20,20} , for 2x - {40,40} , and for 3x position is {60,60} .

Problem

The problem is that 200x200px and 400x400px assets are small for iPad devices in order to achieve the same appearance on all devices.

Question

How to successfully represent / import assets in such a way that I achieve the same (if not the same) appearance of devices / screen sizes without disrupting the location of child nodes?

My occupation:

Take 1 :

I could just use existing 400x400px resources for iPad devices without a retina and 600x600px assets on Retina iPad devices for the home node, but the location of the child nodes would be disrupted. This is due to the fact that the position value of the child has not changed and will still be {20,20} and {40,40} for iPad devices, respectively, while assets will be larger. This will lead to inaccurate child positions in relation to the home node.

Take 2 :

I could also scale the SKScene size (zoom effect) using the usual 200x200px and 400x400px for iPad devices, respectively. This works, and it keeps the work of the child nodes, but the scene / asset playback quality is not as good as it should be. In addition, it looks like a hack, and we do not want it.

Take 3 :

I could also use twice as large assets for iPad devices and double the position of child nodes at runtime. In this case, I would use the 400x400px resource for iPad devices without a retina and the new 800x800px resource for iPad Retina devices. Although it looks great and supports working with child nodes, it looks like a really big position for storing node children at runtime:

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



Thanks for taking the time to read the question!

+12
ios objective-c iphone ipad sprite-kit
Apr 20 '15 at 7:31
source share
4 answers

I could just use the existing 400x400px assets on the iPad without retina devices and 600x600px assets on the Retina iPad devices for the home node, the location of the child nodes would be disrupted. This is because the value of the child’s position will not change and it will still be {20.20} and {40.40} for iPad devices, respectively, while the assets will be larger. This will lead to inaccurate relationships with children at home node.

You can simply scale your home node (and not the scene) to a larger size. All you have to do is set the scale of your home to a value that looks good on large devices. And in fact, instead of checking the iPad, we can come up with a formula that sets the scale based on the size of the screen. Something like the code below should work. Please note that it assumes that your home is ideally located on the iPhone 4, and it will scale sequentially for all large screens. Please note that you can really choose any arbitrary size as the base code, but choosing the smallest screen and scaling is the easiest. Just remember to provide larger textures so that the textures do not blur when scaling.

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

OR

You can use two nodes. The root node to place the "actual" position, and then the image node to display the image. This will allow you to separate your positional data from the displayed. You can change the size and position of your child node image, but you want without messing up the actual position of the node root. You can even include additional node image data in your JSON.




I could also scale the SKScene size (zoom effect) using the normal sizes 200x200px and 400x400px for iPad devices respectively. This works, and it supports positioning of child nodes, but rendering of scene / asset quality is not very good, as it should be. In addition, it looks like a hack, and we do not want it.

This option can definitely work if your application can somehow handle various proportions. For example, you can enable scrolling of a scene if the scale of the scene is larger than the screen of the device. Loss of quality occurs due to the fact that you scale textures that exceed their expected size. You need to provide larger textures to maintain high quality while scaling. In this case, you could just use your 600x600 images (or maybe even more) and allow scaling with scaling. For example, in my RTS Sprite-Kit game for OS X, I scale the entire scene to get the same view of all devices. And I do not lose any quality, because I am sure that I provide very large textures, so there is no loss of quality when scaling.




I could also use twice as large assets for iPad devices and double the position of child nodes at runtime. In this case, I would use 400x400px for non-mesh iPad devices and the new 800x800px assets for iPad retina devices. Although it looks great and keeps the child nodes positioned, it looks like a really big commit of breaking the child node at run time with this:

This may also work, especially if your iPad requires a special layout. However, if possible, avoid checking specifically for the iPad and instead use the screen size to create layout rules so that your nodes dynamically change all screen sizes (see the line above). Sometimes this is not possible if your iPad layout is very different from the iPhone, in which case you will have no choice but to check the iPad.




All three of these solutions are good. I would not have thought that one of them was “hacked”. They all work for different purposes. You need to find the solution that is best for your game.

I would also recommend that you see my two answers below. Not sure, but they can help you understand universal positioning and scaling in the Sprite Kit.

stack overflow

stack overflow

Good luck with the game, let me know if you have any questions.

+6
Jun 13 '15 at
source share

There is no easy way to do what you want. One approach is to use a fixed screen size on your devices. The iPhone 5 is fully suitable for the iPhone 6+, everyone uses a 16: 9 aspect ratio for their screens. While the iPad and iPhone 4s and earlier, everyone uses a 4: 3 aspect ratio.

Before introducing GameScene, you can determine the aspect ratio of the screen, and then set a fixed view size similar to this in 16: 9 format:

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

or is it for 4: 3

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

The exact values ​​really do not matter, only the coefficients.

Knowing the exact size of the screen will allow you to place objects more accurately, regardless of the screen of the iPhone 5 or screen 6+.

+2
Jun 15 '15 at 13:38
source share

Using image objects, you can also specify the IP version of the image.

However, there really is no way to add some additional logic to your application, branching out depending on whether your work is done on the iPad and whether the position is adjusted manually.

We could discuss how best to enable this: I'm not a fan of this "if I'm not this device" checks everything throughout the code. Create an abstract superclass and two subclasses, each processing layout (or whatever you want to name) for one interface idiom. You will only need to check once (when creating them), and polymorphism will take care of the rest.

0
Jun 13 '15 at 9:35
source share

You can use software like PaintCode to dynamically generate a texture that perfectly suits your needs.

All you have to do is determine the frame sizes for each of your devices.

0
Jun 13 '15 at 15:16
source share



All Articles