Am I overthinking this? (Multi-resolution support)

So I created a spreadsheet containing all of the screen resolution s I’m likely to encounter in the wild

(there is a link to it from my blog if you’re interested)
http://www.pooperp1g.com/blog/

Against each resolution I have put 4 different resource resolutions (2048 x 1536, 1920 x 1080, 960 x 640 and 570 x 320) which I decided upon after experimentation and looking at the various resolution ratios etc.

For each screen resolution I calculate the scale factor and visible offset for each of my resource resolutions.

Then, for each device resolution I decide which resource resolution is most appropriate (essentially, one that doesn’t scale too big or too small, and doesn’t cut off too much width (I’m assuming a fixed height policy all of these)

So I end up with a relatively simple formula to decide which resource resolution to use …

    // 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 }};

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
        glview = GLViewImpl::createWithRect("PooperPig", Rect(0,0,1920,1280));

        director->setOpenGLView(glview);
    }
    
    
    // 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;
    
    
    // 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 = ratio;
            }
        }
        
        
    }
    // so now we should have found which resource to use
    searchPaths.push_back(found.directory);
    
    CCLOG("Using %s widthDiff %d ScaleFactor %.2f", found.directory, widthDiff, scaleFactor);

Do you think this is over complex? Is anything wrong with it in principal? Is it sensible to provide resources at these three resolutions?

I’d appreciate any advice you may care to offer :smile:

2 Likes

I for myself never really tried to understand multi resolution support because I thought it feels really early and not technically matured.

If I understand the default approach correctly than we compare the resource resolutions with the device resolution and choose the resource which is higher then the device resolution (of course we compare only height or width).

Your approach looks additionally how much the pictures needs to be scaled and can choose higher resources even then the device resolution is lower. So that it just needs to scale 0.9 instead of 1.8 (for example).
I think that should be nice and good o.o

Pls correct me if I understood something wrong.

Doesn’t cocos2d-x already offer multi-resolution support in their pipeline? why did you reinvent the wheel with that complex calculation. Usually for multi-resolution, I combined what cocos2d-x has offered with this http://v-play.net/doc/vplay-different-screen-sizes/ and adjust the size a little bit.

So I classified all screens resolution into 3 design size categories which are: RETINA_HD (RETINA), HD and SD. And the design size for each categories are as follow:

#define SCREEN_WIDTH_SD     627
#define SCREEN_HEIGHT_SD    396
#define SCREEN_WIDTH_HD     1254
#define SCREEN_HEIGHT_HD    792
#define SCREEN_WIDTH_RETINA 2508
#define SCREEN_HEIGHT_RETINA 1584

#define GAME_WIDTH_SD       528
#define GAME_HEIGHT_SD      360
#define GAME_WIDTH_HD       1056
#define GAME_HEIGHT_HD      704
#define GAME_WIDTH_RETINA   2112
#define GAME_HEIGHT_RETINA  1408

From the previous link, we need to set the aspect ratio for the design size around 19:12 and design everything that happened in the gameplay should be inside a 3:2 aspect ratio screen in order to maintain support for all screen resolution without cutting anything during gameplay. As you can see from the code snippet, all those design size categories have the same pattern such as: HD design is half of RETINA design, and SD design is half of HD design. Thus can make everything easier when the artists made the assets for the game. They just need to create the assets for the largest resolution, then resize the image accordingly

Then on the AppDelegate, we just need to implement multi-resolution calculation from cocos2d-x pipeline. In my case, I’ve decided to design the game without showing any black border, so I used NO_BORDER resolution policy and design everything on the largest resolution.

auto screenSize = glView->getFrameSize();
auto designSize = cocos2d::Size(SCREEN_WIDTH_RETINA, SCREEN_HEIGHT_RETINA);
auto gameSize = cocos2d::Size(GAME_WIDTH_RETINA, GAME_HEIGHT_RETINA);

std::vector<std::string> searchPaths;

if(screenSize.height <= SCREEN_HEIGHT_SD) {
    searchPaths.push_back("SD");
	director->setContentScaleFactor(SCREEN_HEIGHT_SD/designSize.height);
    cocos2d::log("Set SD Design Res");
} else if(screenSize.height <= SCREEN_HEIGHT_HD) {
	searchPaths.push_back("HD");
	director->setContentScaleFactor(SCREEN_HEIGHT_HD/designSize.height);
    cocos2d::log("Set HD Design Res");
} else {
	searchPaths.push_back("RETINA");
	director->setContentScaleFactor(SCREEN_HEIGHT_RETINA/designSize.height);
    cocos2d::log("Set RETINA Design Res");
}

cocos2d::FileUtils::getInstance()->setSearchPaths(searchPaths);
glView->setDesignResolutionSize(designSize.width, designSize.height, ResolutionPolicy::NO_BORDER);

Then cocos2d-x will do all the complex things by itself and you don’t need to worry about this anymore.

well, the bad thing about this kind of implementation is we need to put the assets in a designated folder’s name and make the folder as blue folder in Xcode project which is sometimes annoying because you need to clean and rebuild everything when you add new assets into the folder.

I hope this can be helpful.

You understood exactly what my thoughts were!

When I looked at all the different resolutions available, it seemed to me that simply providing three resource sizes, and basing their choice on either width or height was over-simplifying things - but I was concerned that i was over-complicating things!

Thanks.

The only complexity I have added (as I am using Cocos multi-resolution support ) is in deciding which resource to use.

My aim was to lose as little as possible from my resources (when they are truncated to fit) and also to scale them as little as possible.

It’s interesting! I ran your standard method through my spreadsheet - and the scale factors and truncated pixels compare favourably to my solution! In other words, my method is no more accurate at selecting a suitable resource than yours!

The only real difference I can see is that yours will always scale a resource down - mine aims to sale in either direction, depending on which method owuld give the least scaling and lost pixels.

Perhaps I am over complicating it!

@wiwing
The other thing I notice is you are using the no border policy, which scales horiz or vert to fit the resource into the screen.

I want to use fixed height, as it is important that the full height of my design is shown, and I don’t want black bars top and bottom.

using the design resolutions you mention would leave lots of black bars, I think :frowning:

@Maxxx yeah, I’m using no border policy because I don’t want to leave any black bars on my screen thus why I create this design resolutions to meet the requirements for all available aspect ratios and different kind of devices, and you can get more efficiency on memory usage especially when the player uses low-end device. From what I’ve seen on your solutions, you’ll have problems when there is different kind of aspect ratio that is not listed on your resources dictionary (let’s say 800x480 or any 16:10 aspect ratio) and it’ll burden low-end devices a lot.

I’ve made sure that all my resources, when scaled using fixed height, still fill the screen with no borders at all the resolutions they are used for - so I will never have borders, and always exactly fill the height.

I guess using no border is less of an issue, except then I may lose top and bottom AND/OR left and right - which, if it’s ok for your App is great - but I really wanted to keep the entire height of my App visible.

well if you want to keep the entire height of your app visible, then you can use your solution but it’s kinda make everything more complex … since the coordinate system will also get affected by that or maybe not, I’m not sure since I haven’t tried your solution
the other solution is you can design your game with extra height which you don’t mind if it got clipped like what I’ve done, I design my game entirely on Game Screen (3:2 aspect ratio) so I don’t mind if the excess width/height got clipped as long as the Game Screen is shown fully.

Yeah - I think it just depends on the game itself whether you can get away with that.

Essentially what you end up with is a game playing on a window in the middle of the device - even though that might not be immediately obvious to the player

I was thinking of doing it like this and moving my HUD around to accommodate different aspect ratios and resolution - but that just got even more complex!

Does it matter whether a device is 4 inches or 5 inches or 6 inches or 10 inches?

Or all what matter is how many pixels are there in width and how many in height of a device?
(I mean while designing the assets and while adjusting it along with the cocos multi resolution policies)

Thanxx :smile:

As far as programming goes, the physical device size doesn’t matter, just the screen resolution.

Then where I should concern it?
While designing assets?

I would ignore it.

I’m not sure you can even find the physical dimensions of a screen by code.

If you run at 1024 x 768 on a phone with a 4 inch screen and then ran the same game on a 20 inch monitor running at 1024 x 768 then I would expect it to look identical - i.e. the physical size of a sprite would be 5x as big on the monitor.

the alternative would be that you would need to shrink the size - so a 25 pixel wide sprite on the phone would only be allowed to be 5 pixels wide on the monitor - which would look terrible!

Since you told me that we cannot get the physical size of the screen with code, then how will I do

I think you want to say vice versa…

Ok finally, do I need to care physical size of screen while designing my assets !!
Like bothering how will it look like on the larger screen with same ppi?

I think ppi matters and not the exact resolution. Isn’t it? :smiley:

THIS ONE IS REALLY TROUBLESOME AND THE HEIGHT OF ALL MY DOUBTS IN MULTI RESOLUTION!!

@Maxxx

Hi, please see my last post also.

@slackmoehrle, could you also please look to my following doubt!!

Okay now,

I suddenly came to realize this
There are android tablets as well as mobiles with same resolution as AxB for both.

Visualize portrait layout:

I am having 4 rectangles sprites to be arranged in a row in such a manner that it is easier for the user to type, I mean in fast typing user does not have to lift his fingers much!

So, suppose I am designing my game for this mobile. I can allow my row to entirely cover the screen’s width, i.e my left edge of left rectangular sprite touches the left edge of mobile and right rectangular sprite touches the right side of the mobile.
And it will be easier for him to type faster because the screen it small !!!

But if I let this code run for the same resolution devices but higher physical size. Then those rectangles sprites will become more wider and longer in height too!!
BUT FINGERS AND HANDS of my user won’t be that big to adjust!!!

So, I need to detect that if it is a tablet, then I should leave some border on the edges unlike mobile case!!

I hope you got my problem, right !!

Thanxx :slight_smile:

No. Say on a small device 10 pixels take up one cm
A larger device with the same pixel resolution, 10 pixels would take up more than once cm - so to make our object take up one cm again, we would have to reduce the number of pixels in it.

Honestly, I don’t know what your app/game is doing, so I can’t tell you if you need to take into account the physical screen size. I don’t know of any app that does - but someone is bound to be doing so somewhere.

Honestly, it depends what you are trying to achieve.

If you want your sprites to look identical (i.e. have the same physical size) across all devices, then you would need to take pixels per inch into account.

Are you saying you want to display (for example_ four rectangles on screen, and regardless of the device, you want them always to appear 1cm x 2cm ?

If that is the case then you do need to take into account the number of pixels per inch of the device.

This link tells you how to do that - (and also shows you how to find the physical screen dimensions)

Something similar. But actually I can allow my 4 rectangle sprites to cover the entire width of the screen when aligned adjacent to each other.
But in tablet the size of the rectangular sprites can be a little bigger but not enough that they will cover the entire width of the screen as above because otherwise player won’t be able to type comfortably. But yes, size can be a little bigger but not according to the logic for mobile devices!!

Hence, it asks for the need to know ppi or physical size of the screen!

Or it is possible to find whether a device is a mobile/phablet or tablet
Becuase I can afford my rectangles to cover entire width uptil phablet devices but not tablet

Let me go through the link. I think we can also find out dpi of the device in cocos2d-x!!

You can get DPI via: Device::getDPI();
But I found that DPI will not help you at all.

I have the problem that some of my testers complain that font is too small on their phones. While on tablets the font looks alright.
So here’s a few measurements I’ve tried (I’m using portrait only for my app):
Tablet, iPad1 - DPI: 132, 768x1024
Tablet, Samsung Tab 3 - DPI: 213, 800x1280
Phone, iPhone6 - DPI: 326, 750x1334
Phone, S4 Mini - DPI: 320, 540x960
Phone, S2 - DPI: 160, 480x640

So there’s really no way to understand from DPI if it’s a phone or a tablet.

I wish I knew about wiwing’s multi-resolution solution when I started on the app. Because now I’ve made special cases depending on which resolution the device has and done all the positioning & scaling manually.
It’s not too late to try it out tho. But wiwing’s solution will NOT help with fonts being too small on some devices.