Tile size, retina vs non-retina, iPad vs iPhone - ios

Kind of a fun question. I am hoping that is generates a lot of good thinking.
I am in the design, early alpha stage of my current orthogonal game project. I am experimenting with different tile sizes. A few questions as I would like to step off on the right foot.
Should we differentiate tile size (80x80, 32x32 etc) on retina vs. non retina displays, iPhone vs iPad displays?
What is a good recommended tile size that accommodates both the designer and the artist... and why?
Goals:
I would like to a clean, crisp visuals no matter the display format. Cartoony, colorful 16bit to 32bit images no matter the display.
I would like to keep to a 1024x1024 texture size for my atlas. I am hoping this will give me enough tiles to make the world look good and not crush my tile map system.
My current map size is 200 tiles wide x 120 tiles high. The map will be a a low detail (nautically focused) mercator projection of Earth.
Thanks in advance for all the good advice.
E

I usually try to make my games for iPad screen aspect where I'm making sure that the important elements are in a smaller Safe Zone. And the UI can be anchored on specified distance from the edges. Then for iPhone screen aspect I crop a small portion of the screen and layout the UI accordingly.
So if you are working in landscape here are the sizes you need to support:
480x320 - iPhone (0.5)
960x640 - iPhone Retina (1)
1024x768 - iPad (1)
2048x1736 - iPad Retina (2)
The number in brackets indicate the scale. I just like picking iPad (1024x768) for my ingame units. At this point I have all textures in 3 sizes, since I'm using OpenGL I use different mipmaps for each resolution I need. My texture loading function can skip mipmap levels so that on devices that I don't need high res I safe memory and loading time.
Depends if you need to click on individual tiles. In case you need to I'll suggest using 64x64 on iPhone (480x320) 256x256 on iPad Retina (2048x1736). Having all your art in power of 2 is always good. If the size is too large then consider 48x48 for iPhone and 192x192 for iPad Retina. If your game requires you can have smaller tiles but consider having larger active zone around the entities that you have to click (hopefully not every tile will be clickable).

I faced a similar issue a while ago and realized I was tackling the problem from the wrong angle.
You first need to consider the average finger/thumb size of the user and determine how many pixels/points consume that space.
From there you can derive the non-Retina Display pixel units and Retina Display point units to use.
N.B. that a game that might play well on the iPad might not work on the iPhone if the user's fingers obscure the view.

Related

'Display Zoom' iPhone 6/6s setting blurs graphics

I'm writing a project in Xcode 7 / Swift 2 that it is optimized for iPhone 6/6s (i.e. the project has a launch screen file and launch screen images for iPhone 6/6s).
Fortunately or unfortunately, iPhone 6 users have the ability to turn on the ‘Display Zoom’ setting on device which enlarges elements of the interface. When turned on, this setting effectively enlarges a standard iPhone 5 screen size to fit in the iPhone 6 screen space, upsampling to x1.171875. This upsampling causes elements that are raster based such as images, icons, or views that contain UIBezierPath() drawings to display blurred (mildly but noticable).
A few questions:
Appreciate any experienced responses on this conundrum. Thanks.
1 - How can I instruct elements (e.g. a UIView) on the Storyboard in code to disregard the Display Zoom setting when the user has turned it on?
2 - What techniques are there to ensure pixel perfect accuracy remains when Display Zoom is on? (e.g. Is it possible to render graphics using OpenGL rendering, if so, how?)
3 - Is it possible to replace a x2 image with a x4 image to reduce any blurring when Display Zoom is on? (i.e. will iOS downsample a x4 image to x2 image on iPhone 6?)
4 - How can UIBezierPath() drawings maintain pixel perfect accuracy when Display Zoom is on?
There's nothing you can do about this. A user who chooses zoomed mode is deliberately throwing away pixel accuracy. The points in the drawing no longer match the pixels on the screen one-to-one (or one-to-two or one-to-three or any integral ratio). This choice therefore blurs the screen for everything the user does, not just your app.
Nor can you detect what is happening, because in effect zoomed iPhone 6 is presented to your app as an iPhone 5 (and a zoomed 6 Plus is presented to your app as a 6).
As #matt says, there's nothing you can do about this for normal UIKit content
However, for Open GL ES or Metal content, you are able to opt-out of the sampling that the device does, and render straight into the device's physical coordinates - allowing for pixel perfect drawing.
In a graphics app that uses Metal or OpenGL ES, content can be easily rendered at the precise dimensions of the display without requiring an additional sampling stage. This is critical in high-performance 3D apps that perform many calculations for each rendered pixel. Instead, create buffers to render into that are the exact resolution of the display.
Open GL ES
Set the contentsScale of the CAEAGLayer to the [UIScreen mainScreen].bounds.nativeScale, or use a GLKView which will automatically do this.
You will then want to create your framebuffer with the size of the device's physical coordinates.
Metal
Set the contentsScale of your CAMetalLayer to the [UIScreen mainScreen].bounds.nativeScale, or use an MTKView which will automatically do this.
You will also want to adjust the drawable size to account for the scale (lifted from the docs):
CGSize drawableSize = self.bounds.size;
drawableSize.width *= self.contentScaleFactor;
drawableSize.height *= self.contentScaleFactor;
metalLayer.drawableSize = drawableSize;
See also this interesting blog post on how the iPhone 6 Plus renders content, plus the follow-up post specifically about Display Zoom.

Universal 2D Game Assets and Absolute Node Positioning

I have a question regarding universal game assets and absolute positioning of a SKNodes in Sprite Kit (iOS 8+).
I will try to present my problem through an example as follows:
Imagine a 2D top down game with a SKSpriteNode which represents a house. A house has multiple child SKSpriteNodes which represent chairs, desk, sofa, etc.
I have 3 versions of house asset:
1x - 200 x 200px (Non-retina iPads),
2x - 400 x 400px (Retina iPhones and iPads),
3x - 600 x 600px (iPhone 6 Plus).
Important:
Child nodes (chairs, desk, etc.) positions are defined in a .plist file. Something like this (JSON representation):
children: [
{
position = {20,20};
},
...
]
Since the position is defined in points and not in pixels, everything gets positioned like expected according to device screen scale. For 1x devices the position stays {20,20}, for 2x position is {40,40} and for 3x the position is {60,60}.
Problem:
The problem is that 200x200px and 400x400px assets are way to small for iPad devices in order to achieve similar look and feel on all devices.
Question:
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?
My takes:
Take 1:
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.
Take 2:
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.
Take 3:
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:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
position.x *= 2.0f;
position.y *= 2.0f;
}
Thank you for taking the time to read the question!
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.
You can simply scale your house node (not the scene) to a larger size. All you need to do is set the scale on your house to a value that looks good on larger devices. And in fact, instead of checking for iPad we can come up with a formula that sets the scale depending on the size of the screen. Something like the code below should work. Note that it assumes your house is positioned perfectly on a iPhone 4 and it will consistently scale to all larger screens. Note that you really could pick any arbitrary size as your base case, but choosing the smallest screen and scaling up is easiest. Just be sure to provide larger textures so that the textures don't become blurry when scaled.
[house setScale:self.scene.size.width/320.0];
OR
You could use two nodes. A root node for holding the "actual" position, and then an image node child for displaying the image. This will allow you to separate your positional data from what's being displayed. You could resize and position your child image node however you want without messing with the actual position of the root node. You could even include this extra image node data in your 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.
This option can definitely work if your App can handle the different aspect ratios in someway. For example you could allow scrolling the scene if the scene is scaled larger than the device screen. The loss in quality occurs because you are scaling the textures larger than their expected size. You need to provide larger textures to keep the quality high when zooming. In this case you could probably just use your 600x600 images (or maybe even larger) and let it scale with zoom. For example, in my RTS Sprite-Kit game for OS X I scale the entire scene so I get the same look across all devices. And I don't lose any quality because I make sure to provide very large textures so there is no loss in quality while scaling.
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:
This could also work, especially if your iPad requires custom layout. However, if possible avoid checking specifically for iPad and instead use the screen size to create layout rules so your nodes dynamically adjust on all screen sizes consistently (See the line of code 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 for iPad.
All three of these solution are good. I wouldn't consider any one of them "hacky." They all work for different purposes. You need to find the solution that works best for your game.
I would also recommend you see my two answers below. Not sure but they may help you with understanding universal positioning and scaling in Sprite Kit.
https://stackoverflow.com/a/25256339/2158465
https://stackoverflow.com/a/29171224/2158465
Good luck with your game, let me know if you have any questions.
There's no easy way to do what you want. One approach would be to use a fixed screen size on your devices. The iPhone 5 all the way up to iPhone 6+ all use a 16:9 aspect ratio for their screens. Whereas the iPad and iPhones 4s and earlier, all use a 4:3 screen aspect ratio.
Before presenting your GameScene, you can determine the screen's aspect ratio and then set a fixed view size like this for 16:9:
GameScene *startGame = [[GameScene alloc] initWithSize:CGSizeMake(736, 414)];
startGame.scaleMode = SKSceneScaleModeAspectFit;
or this for 4:3
GameScene *startGame = [[GameScene alloc] initWithSize:CGSizeMake(1024, 768)];
startGame.scaleMode = SKSceneScaleModeAspectFit;
The exact values really do not matter, only the ratios.
Knowing the exact screen size will allow you to place objects in more precise manner regardless of iPhone 5 screen or 6+ screen.
Using image assets, you can also specify iPad versions of an image.
However there's not really a way around adding some extra logic to your app, branching depending on whether or not your running on the iPad, and adjusting the position manually.
We could discuss how to best incorporate that though: I'm not a fan of this "if I'm not this device" checks all throughout the code. Create an abstract superclass and two subclasses, each handling layout (or whatever you may want to call it) for one interface idiom. You will the only need to check once (when instantiating these) and polymorphism will take care of the rest.
You can use a software as PaintCode to dynamically generate texture perfectly sized to your need.
All you have to do is to define the frame' dimensions for each of your devices.

How can I use GLKView to draw at a lower resolution?

I have an app based on "OpenGL Game" Xcode template, for everyday testing/dev I would like to render full screen but at lower resolution in simulator (e.g. 1/2 or 1/4). Any efficient/savvy way to put this in place?
(in case anybody wonder, I want to do this because my app is running very slow in simulator, so rendering at a smaller resolution would make testing/debugging a lot more programmer-friendly)
The contentScaleFactor of the view is 2.0 by default on a Retina display. If you reduce the scale factor, GLKView automatically uses a smaller framebuffer and scales its contents up to screen size for display.
Scale factor 1.0 is half size (or the same number of pixels as a non-Retina screen). 0.5 would be quarter size — big, chunky pixels on any display. Non-integral scale factors between 1.0 and 2.0 work, too, and can be a great way to compromise between quality and performance on a Retina display.
Update: just had a vote remind me of this answer. I'm surprised I wouldn't have said this originally, but I may as well add it now...
The iOS Simulator runs OpenGL ES using a software renderer (i.e. on the host Mac's CPU, not its GPU). That's why it's slow. Performance characteristics and rendering results can vary from renderer to renderer, so never trust the simulator for anything OpenGL/GPU-related (except perhaps in very broad strokes).

Cocosd2d and body.m_radius depend on device type

I'm little bit confused by points in cocos2d.
I have universal game and when I set possition of body in points, it works well over all devices (iPhone, iPhone HD, iPad, iPad HD). I made textures in 4 sizes with cocos2d suffix and it works well too.
But I have body (b2CircleShape) and i need to set m_radius of this circle.
I have this lines:
b2CircleShape myDynamicBody;
myDynamicBody.m_radius=0.48;
Value 0.48 is optimized for iPhone HD and it works well on both iPhone (iPhone and iPhone HD) but on iPad and iPad HD devices it is very small. What should I do? Check type of device and when I find iPad multiply it in 1.33 (when I tried to multiply it in 1.33 it worked fine on both iPads).
Or is there any better (or recomended) way, how to solve this problem?
Thank you for advices
You should adjust your points-to-meter (PTM_RATIO) on iPad.
The reason for 'points', is that Box2d is tuned to run physics simulations for bodies between 0.1 and 10 meters, with a typical body being about 1x1 meter. It will still work for bodies outside of these sizes, but will be less reliable.
On the other hand, you've got a screen with either ~320x480 or 1024x768 points of resolution. Therefore we need a way to convert the sprite representation to a size that is suitable for Box2d. For this we use the 'points-to-meter' ration (PTM).
If your typical sprite is 64x64 you should choose a PTM ratio of 64. This will make box2d see you 64x64 sprite as 1x1, which is an ideal size to run simulations on it.
Having explained that, the reason that the PTM_RATIO varies between phone and pad form factors is now obvious: Its because they have different resolutions. A sprite that is 64x64 on iPhone would be approx 128x128 on tablet.
So to get your PTM_RATIO on ipad, choose a sprite on iPhone and look at the corresponding size on iPad. Now multiply the iPhone PTM by the ratio of the sizes beteen those two images.

Which screen resolution should i use?

I'm planning on making my first game in xna (simple 2d game) and i wonder which screen resolution that would be appropriate to target the game against.
Resolution for a 2D game is a difficult issue.
Some people ignore it. World of Goo (for PC), for one very famous example, simply always runs at 800x600 on the PC, no matter what. And look how successful it was.
It helps to think about what kind of device you will be targeting. Here are some common resolutions and the devices they apply to:
1280x720 (720p, Xbox 360 "safe" resolution - free hardware scaling, works everywhere)
1920x1080 (1080p, Xbox 360 maximum resolution - can't auto-scale to all resolutions)
800x480 (Windows Phone 7)
1024x768 (iPad)
480x320 (iPhone 3GS and earlier)
960x640 (iPhone 4 retina display)
Android devices also have similar resolutions to WP7 and iOS devices.
(Note that consoles require you to render important elements inside a "title-safe" area or "action-safe" area. Typically 80% and 90% of the full resolution.)
Here is the Valve Hardware Survey, which you can see lists the common PC resolutions (under "Primary Display Resolution").
Targeting 800x480 for a mobile game, or 1280x720 for a desktop/console game, is a good place to start.
If you do want to support multiple resolutions, it is important to think about aspect ratio. Here is an excellent question that lists off some options. Basically your options are letter/pillar-boxing or bleeding (allowing for extra rendering outside "standard" screen bounds - like a title-safe area), or some combination of the two.
If your graphics need to be "pixel perfect" and simply scaling them won't work, then I would recommend targeting a series of base resolutions, and then boxing/bleeding to cover any excess screen on a particular device. When I do this, I usually provide assets for these target screen heights: 320, 480, 640, 720, 1080. Note that providing 5 versions of each asset is a huge amount of work - so try to use scaling wherever possible.
Many choices about resolution handling will depend on what style of game you are making. For example: whether you try to match a horizontal or vertical screen size will depend largely on what direction your game will mostly scroll in.
When I first started with c++ graphics I used 320*240, or 800*600 when I had to use larger images. But it's really up to you, whatever you prefer. As long as you don't use stupid values like 123*549 or something.
'normal' resolutions include but are not limited to:
160*120
320*240
640*480 (probably the most common)
800*600
1024*768

Resources