cocos2d / cocos2d-x

Cocos2d-x is a suite of open-source, cross-platform, game-development tools utilized by millions of developers across the globe. Its core has evolved to serve as the foundation for Cocos Creator 1.x & 2.x.
https://www.cocos.com/en/cocos2d-x
18.24k stars 7.06k forks source link

Multi-resolution code in the default template is confusing and needs to be changed #18492

Open Priority10 opened 6 years ago

Priority10 commented 6 years ago

Since I did not receive any feedback on the forum, I publish it here. You can do whatever you want with it, use one of the options, or close this issue and forget about it. I do not care.

Short version.

Firstly, I do not think this is the best solution ever, but I think that this is a good option to illustrate how it works.

The aspect ratio of the Design Resolution is 16/9 to better illustrate NO_BORDER. Convenient scale factors (x1, x2, x3).

...

static cocos2d::Size designResolutionSize = cocos2d::Size(960, 540);

static cocos2d::Size smallResolutionSize = cocos2d::Size(960, 540);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1920, 1080);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2880, 1620);

...

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);

    auto frameSize = glview->getFrameSize();
    std::vector<std::string> searchPaths;

    if (frameSize.width > mediumResolutionSize.width)
    {        
        director->setContentScaleFactor(largeResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("largeResources");
    }
    else if (frameSize.width > smallResolutionSize.width)
    {        
        director->setContentScaleFactor(mediumResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("mediumResources");
    }
    else
    {        
        director->setContentScaleFactor(smallResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("smallResources");
    }

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

    register_all_packages();

...

In this case, I just do not like how it works if screen width = resource width, but the screen aspect ratio < 16/9 (only in some cases, like 1920x1200 or 1920x1440 or 960x640 ... ). Maybe I'm just a perfectionist. But this is a good option to illustrate NO_BORDER. I doubt what to choose.

The aspect ratio of the Design Resolution is 4/3, not so good to illustrate NO_BORDER, my inner perfectionist absolutely likes how it works. Convenient scale factors (x1, x2, x3).

...

static cocos2d::Size designResolutionSize = cocos2d::Size(960, 720);

static cocos2d::Size smallResolutionSize = cocos2d::Size(960, 720);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1920, 1440);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2880, 2160);

...

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);

    auto frameSize = glview->getFrameSize();
    std::vector<std::string> searchPaths;

    if (frameSize.width > mediumResolutionSize.width)
    {        
        director->setContentScaleFactor(largeResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("largeResources");
    }
    else if (frameSize.width > smallResolutionSize.width)
    {        
        director->setContentScaleFactor(mediumResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("mediumResources");
    }
    else
    {        
        director->setContentScaleFactor(smallResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("smallResources");
    }

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

    register_all_packages();

...

The aspect ratio of the Design Resolution is 4/3, not so good to illustrate NO_BORDER, more iOS friendly. Personally, I do not like scale factors.

...

static cocos2d::Size designResolutionSize = cocos2d::Size(1024, 768);

static cocos2d::Size smallResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(2048, 1536);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2880, 1620);

...

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);

    auto frameSize = glview->getFrameSize();
    std::vector<std::string> searchPaths;

    if (frameSize.width > mediumResolutionSize.width)
    {        
        director->setContentScaleFactor(largeResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("largeResources");
    }
    else if (frameSize.width > smallResolutionSize.width)
    {        
        director->setContentScaleFactor(mediumResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("mediumResources");
    }
    else
    {        
        director->setContentScaleFactor(smallResolutionSize.width/designResolutionSize.width);
    searchPaths.push_back("smallResources");
    }

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

    register_all_packages();

...

Since there are many similar resolutions like 1920x1080, 1920x1200, 1920x1280, 1920x1440, I prefer to choose the resources based on the longer side of the screen, in the case of the default template it is width.

It is necessary to add 3 folders with resources in the default template.

Priority10 commented 6 years ago

Since the engine has enough open issues, too much in my opinion, I give 2 weeks to this issue, if no one will be interested, then I will close it.

slackmoehrle commented 6 years ago

I will get this on my list of items to review. Ultimately, I would still need engine team members to sign off on anything before a merge.

slackmoehrle commented 6 years ago

@minggo do you have thoughts about replacing this code. Would it be helpful for me to test and post results from a cocos new ... project?

minggo commented 6 years ago

@slackmoehrle yep, go forward please.

Priority10 commented 6 years ago

@slackmoehrle Well, it is been a while. Any chance that something of this will go into 3.18? If you do not like logic or code, I will be happy to discuss this. If you think that the issue should be closed, I will also gladly do it.

slackmoehrle commented 6 years ago

I think we need this too. I just need to get it done. I can use your ideas above to start.

Priority10 commented 6 years ago

Cool.) When do you plan to start working on this?

quangvt commented 5 years ago

Hi guys. Could you give us any status about this issue?

Kabariya commented 5 years ago

Hi, guys we are fetching the same issues any solution for that? or any other way so we can solve multi-resolution problem and game can work on every device

Priority10 commented 5 years ago

This is not exactly an issue of the engine. The engine gives you the tools to support multiple screen resolutions. But you must choose one of the many combinations that suits your game.

In this issue, I only say that the code in the template is bad because a) it does not perform its task b) and bad illustrates what you can do with the engine. But in most cases, you still have to change this code for your game.

Why there is no universal solution? I will try to explain with an example.

In my last project I use portrait mode + designResolutionSize = cocos2d::Size(442, 960) + FIXED_HEIGHT +

static cocos2d::Size smallResolutionSize = cocos2d::Size(720, 960);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1440, 1920);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2160, 2880);

And it works great for me! Well, because I remember that the corners of the screen can be rounded, and the speaker can take part of the screen at the top.

And now let's go to the Google Play store. Look here https://play.google.com/store/apps/details?id=com.outfit7.tomsbubbles I do not know if they use cocos2d-x or not, but judging by the screenshots they use similar logic (portrait mode + wide design resolution + fix height). And it does not work well for them. In some screenshots, you can see only half of the balls in the leftmost and rightmost rows. This is not critical, but not the best solution.

Now look here https://play.google.com/store/apps/details?id=com.king.candycrushjellysaga Again I do not know if they use cocos2d-x or not, but if they do, then I am pretty sure that this is ultra wide design resolution (with safe area 4/3) + FIXED_WIDTH in portrait mode and ultra wide design resolution (with safe area 4/3) + FIXED_HEIGHT in landscape mode. Or they may use ultra wide design resolution (with safe area 4/3) + NO_BORDER with the same result.

So my advice for you is to read the forum, experiment, or ask slackmoehrle to write this documentation which he has long promised.

Kabariya commented 5 years ago

@Priority10 thanks for the explanation. we have found something on the internet and they claim that they are able to solve these issues, can you please look into it, we have tried but we are not getting exactly how they are doing it. link of that PPT (slide number 19-24) https://www.slideshare.net/ogdc/program-farmery-by-cocos2d-x-kien-vnfinal

Priority10 commented 5 years ago

Sorry, I can not open the link. This site can’t be reached ERR_CONNECTION_RESET In any case, it is quite possible that they have a solution, but are you sure that this solution is suitable for your game? Because different games -> different needs -> different solutions.

My point is that you can find a ready-made solution on the Internet, but without understanding how it works, it is quite possible that you will use it incorrectly. Not because you are not smart, but because every solution has limitations that you need to keep in mind. And with the release of such phones as Pixel 3 XL and Samsung Galaxy 10 it becomes almost impossible to create UI that will be 100% visible and will look beautiful on all screens.

Priority10 commented 5 years ago

Quick advice on how to figure this out faster

  1. Now forget about setContentScaleFactor() and setSearchPaths(). Comment (or better delete) all related code and think that you have only one graphic set.

  2. So, it is the time to decide for what resolution this set will be drawn. Learn how setDesignResolutionSize() works. Pay special attention to ResolutionPolicy. Try different designResolutionSizes and ResolutionPolicys, and find out what part of your designResolution will always be visible on different screens with this particular ResolutionPolicy. Aspect ratio is very important thing here.

  3. When you figure out which combination of designResolution and ResolutionPolicy suits you needs, then it is time to find out what setContentScaleFactor() is used for.

  4. Look iPhone X, Pixel 3 XL and Samsung Galaxy 10 and get frustrated again. Just kidding :P Not everything is so bad and there is a solution for this too.