Optimal design resolution and assets folders formation (how to choose one?)

Hi,

I’m still struggling to find optimal design resolution and how to prepare assets folders optimally as well, so that it will cover most mobile device screen sizes out there.

Please share your experience on a topic, it will serve a good job for a beginners like me :smile:

Regards,
Mike.

1 Like

I know that there is a lot of topics on this forum that discuss terms like design resolution/policies, screen aspect ratio, search paths and I looked through some of them but still can’t figure out the solution. :wrench:

Firstly I thought that it will be enough (or at least will cover most of the iOS devices) to have 3 assets folders:

  • HDR: 2048x1536
  • HD: 1024x768
  • SD: 512x384

As in my game the height should be preserved - FIXED_HEIGHT policy should be used. (?)

But after encountering very comprehensive spreadsheet made by @Maxxx:

I start to think what is going on with aspect ratios of different devices and how well does my assets folder formation fit them… And I think that there is a way to improve here for me.
With my current formation I have only 1.33 aspect ratio covered and that is not so good. (?)
But as the spreadsheet showed there is a lot of devices with other aspect ratios that have to be estimated as well.

And finally, what about how to decide search path for the assets?
Is it enough to query screen size of the device and then to choose assets folder with closest resolution?
But what about aspect ratio of the device? If it’s 1.7 and I choose a an assets folder like HD that has closest resolution but differs in aspect ratio - 1.33? In that case choosing other asset folder that will have not the closest resolution but will have the same aspect ration can produce better results, no?
And when the design resolution does come to play?

Regards,
Mike.

3 Likes

I’m using a design resolution of 1024x768 with a “Fixed Width” policy. This is mainly because I have an iPad 2 which is of that resolution. I personally think it would make more sense designing for 4:3 aspect ratio and adjusting it if needed for 16:9 aspect ratio, rather than designing for 16:9 and finding you need to add more art assets or extend them when you are on a 4:3 device.

Asset folders require some thought, because if you want to include “Retina” assets in the same version of the app as your non-retina assets, you end up with a much bigger app. I believe a lot of games split into “My Game” and “My Game HD”. But if you want to stick all assets into the one app, I’d say the HDR, HD and SD folder would do.

The search paths I use are based on the width of the screen. Because my HDR assets are for devices of resolution higher than 1024x768, I check if the width is greater than 1024. The same for a width 512 and SD.

Basically, if design for 2048x1536 and used a fixed width policy, it will handle all the 4:3 devices. The 16:9 will be cut off at the top and bottom, but this just means adjusting your game to make sure vital stuff isn’t cut off, and making sure your UI is positioned correctly.

But what is best may depend on the type of game you are making. I am not sure.

The fixed height policy scales the resources so that a resource the size of the Design Resolution has a height of the size of the screen. It scales it uniformly - so if the screen aspect ratio is the same for both design and real resolution, the screen will fit.
If the design resolution has a ‘wider’ aspect ratio, then some will be chopped off at the edges
If the design resolution has a ‘narrower’ aspect ratio then you will have black bars each side.

I made up the spreadsheet so that I could work out what resolutions I could use so that I always had a resource that, when scaled, would fit the screen width - I didn’t mind losing some off the edges, but didn’t want black bars.

I ended up with 4 resource sizes UHD, HD, STD, LOW as on the spreadsheet. The green highlighted cells show the resolution resource that will be used for the screen resolutions in the list. The actual highlighted cells show how many pixels extra will be chopped off, or how wide the black bar will be (if the figure is negative)

As you can see, it’s not ideal, but it covers all resolutions!

The alternatives as I see it are to do a different version for apple devices (where at least the resolutions are fixed and well known) and another for ‘other’ devices where it is more likely to have variants.

Or put up with losing data at the edges or having black bars.

If you do that then you may end up, for example, scaling an asset up by some fraction, where there is an asset at exactly double the screen resolution, that may look better scaled down by exactly half.

Unfortunately I am the opposite of rich, so don’t have real devices to try all of this on - so I develop as a Mac application and change the window size to test different resolutions. Which isn’t ideal, but at least makes for quick testing!

Design a background screen at 1024x768, and draw on it a sprite at 64x64 - it looks good!
Copy that screen at 2048 x 1536 and you have to draw your sprite at 128x128

If you load the large background and large sprite on a 2048x1536 device, no scaling is required.
Now load it on a 1920x1280 screen and it needs to scale it - but how does cocos know by how much?
You need to tell it that your images were designed at 2048x1536 so it can apply the scaling - it can’t know that the 128x128 sprite needs to be scaled otherwise.

Hope that helps a littleindent preformatted text by 4 spaces

1 Like

Thanks, that should be a good idea as well.

You mean assets resolutions by folders not the design resolution, did you? I thought that only one design resolution could be set in the game.

Thanks for this clarification.

Yeah, you did a great job. Probably I’ll use the same formation as you did.

Yes, that is exactly my concern! How to take this possible situation into account??

It helps a lot! :thumbsup:

@Maxxx can you refer to my question please?

Yes - I"m an ass! I will fix up the post to avoid confusing others!

It still actually confuses me!

For my benefit, I think the design resolution can best be described as being:

The resolution used for the positioning of assets in the app, rather than for scaling.

Sorry for the delay in the response - I thought I had replied a while ago - turns out I hadn’t clicked the Reply button!

@Maxxx can you answer this question (actually more impotent then the first one)? :slight_smile:

I should had to split my post :slight_smile:

OK - bear in mind I am still experimenting, learning too - so this could all be a waste of time:

What I currently do is something like below.

// Information about resources
typedef struct tagResource
{
    cocos2d::Size size; // The size that this resource is designed for
    char directory[100]; // The name of teh directory containing resources of this type
} Resource;

// Define all our resource types and locations
static Resource ultraResource   =  { Size(2048, 1536), "UD"};
static Resource hiResource      =  { Size(1920, 1080),  "HD" };
static Resource stdResource     =  { Size(960, 640),   "SD" };
static Resource lowResource     =  { Size(570, 320),   "LD" };

// Declare the resolution we designed the game at
static Size designResolutionSize = Size(1920, 1080);

// Declare an array containing the resource descriptions, from largest to smallest
static std::array<Resource,4>  resources{{ultraResource, hiResource, stdResource,lowResource }};



    // Tell cocos our design resolution and our resolution policy
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::FIXED_HEIGHT);

// The vector we will use to build a list of paths to search for resources
std::vector<std::string> searchPaths;

// Get the actual screen size
Size frameSize = glview->getFrameSize();

// Define a silly scale factor so we know when we have calculated it
float scaleFactor = -1;
int widthDiff = 999;
Resource found = ultraResource; // Default to this in case we find a resolution we plain can't figure out!


// Look through our resource definitions
for (auto resource : resources)
{
    // Calculate the Horizontal ratio for the resouces (i.e. Resource Height / Device Height
    float ratio = resource.size.height / frameSize.height;
    
    // Calculate the scaled widths based on the horizontal ratio
    float scaleWidth = resource.size.width / ratio;
    
    // Calculate the Width Differences (i.e. how much bigger is the resource than the screen, width wise- so how many pixels are we going to lose?
    int diff = scaleWidth - frameSize.width;
    
    // If the width difference is < -1 we'd have black bars, so ignore it (single pixel is fine!)
    // If the scale factor is > 2 we're scaling a bit too much, ignore it
    // If the scale factor is < 0.5 we're scaling a bit to much, ignore it
    
    if (diff >= -1 && ratio <= 2 && ratio >= 0.5)
    {
        // Use this one if it is the lowest width difference
        if (diff < widthDiff)
        {
            widthDiff = diff;
            found = resource;
            scaleFactor =resource.size.height /  designResolutionSize.height ;
        }
    }
    
    
}
// so now we should have found which resource to use
searchPaths.push_back(found.directory);

Globals::resourcePath = found.directory;

CCLOG("Using %s widthDiff %d ScaleFactor %.2f VisibleOffset %.0f, %.0f", found.directory, widthDiff, scaleFactor, director->getVisibleOrigin().x, director->getVisibleOrigin().y);

director->setContentScaleFactor(scaleFactor);



searchPaths.push_back("PropertyLists");
searchPaths.push_back("PropertyLists/Particles");
searchPaths.push_back("Fonts");
searchPaths.push_back("Sounds");
searchPaths.push_back("Images");
searchPaths.push_back("Images/Terrain");
searchPaths.push_back(FileUtils::getInstance()->getWritablePath());


FileUtils::getInstance()->setSearchPaths(searchPaths);
5 Likes

@Maxxx thanks for sharing the code! :thumbsup:

So far this approach works well for you, both on iOS and Android devices?

Does the code takes into account the actual devices orientation?
I mean, if my game supposed to run in portrait orientation, do I have to adapt the code? It seems to work for landscape orientation only or I’m wrong…

Does somebody know if glview->getFrameSize() takes into account the actual device orientation?

Regards!

I currently develop for Mac - that way I can change the screen resolution to anything at all to emulate different device sizes - and this approach seems to work fine for everything I have tried.

I must admit, this means I don’t have to worry about orientation - but what I have done in the past is simply test if W < H and swap them if it is.

I am not sure how getFramesize() handles orientation so that’s what I would probably do here.

And yes - my code is for landscape only because my game is designed for fixed height landscape - I have no intention of allowing it to be run in portrait mode!

Cheers

Max

1 Like

Will have to do these adaptations as my game is in portrait mode with fixed_height, thanks!

Hi Guys,

I knew until unless I try out my doubts, I won’t be satisfied.
So, i tried our with images designed my own template like Frahaan did, and during the designing of the template, I visualized that… ya there are a lot of assets sizes which share the same aspect ratio and can be scaled down to fit sizes without compromising the boundary cuts.

So, here’s what I found -

point 1. If we design our game assets with the highest resolution of 2560 x 1440, which on division gives 1.77
then it can be scaled down of all the resolutions which share the same aspect ratios.

Therefore, I noted down all possible android resolutions and found this -

( 854 x 480 ) * 3
( 960 x 540 ) * 2.66
( 1136 x 640 ) * 2.25
( 1280 x 720 ) * 2
( 1920 x 1080 ) * 1.33

all these counts to 2560 x 1440. That means we can have our entire design built with 2560 x 1440
and cover a hell lot of devices ( including iphones ).

Now, as devices with low memory and performance ( specifically the devices under 1136 x 640 ) needs assets of smaller sizes. Therefore, I would use 1136 x 640 as the design resolution and the asset size, then assets can be scaled down based on the calculation done on point 2.

Moving on, Ipad and Ipad Retina are pain in the butt ( i don’t know why the came up with such odd resolutions ).
So, for that we need to design asset 2048 x 1536 which is twice of 1024 x 768 and can be scaled down.

Now, the final part -
Some devices has strange width or height. ( mostly has aspect ratio of 1.6 )
Such as,
2560 x 1600
1920 x 1200
1280 x 800
960 x 640

To make our assets work on every device, we need to cover these resolutions also.
But, I will use same assets for -

HDR ( 2560 x 1440 )
HD ( 1136 x 640 )
IPAD ( 2048 x 1536 )

and to fit these assets to the screen we have to compromise a bit of our assets
( width/height will be clipped off depending on landscape/portrait )

point 2. The calculation assumes NO_BORDER with 100 px non-playable area (from each sides) of the design.

auto screenSize = glview->getVisibleSize();
Director::getInstance()->setContentScalingFactor( min( screenSize.width / designSize.width , screenSize.height / designSize.height));

and the designResolution sizes would be -

2560 x 1440
1136 x 640 and
2048 x 1536

based on calculations.
I see it covers almost all devices.
Your suggestions are always welcome.

1 Like

This all is a really interesting topic!
I would add another suggestion: what about the download of a bunch of assets after app installation? You could check the device resolution and manage the better fitting one, then download it from your server. In this manner, you can shrink down the package MBs and also change your images without a new submission (you just need to change them on your server and download them again).
I’m thinking to put in place this approach, but at this time I’m still studying the better way to do it.

I am sure this topic needs an update. :slight_smile:
I’ve come a long way since last time I created this post.

I do all sorts of optimisations now.
I would find time one day to post them over here for others to benefit.