Confused by the sprite size and desinged size and all the size stuff

Hi,

New to cocos2dx, find it very confusing to understand what does all size work in the framework.

I found when doing a scale thing in the appdelagate, the result of sprite->getContentSize() as well as sprite->getBoundingBox().size will change due to change of glview.

Since I want to the designed resolution to be 1920x1080 targeted to the main mobile devices, but I want my working PC resolution to be smaller so that the game window won’t take “too much” of the screen while I am working.

So I made change to the AppDelegate.cpp as following

static cocos2d::Size designResolutionSize = cocos2d::Size(1920, 1080);
static cocos2d::Size workingResolutionSize = cocos2d::Size(1920 * 0.5, 1080 * 0.5); 
...
bool AppDelegate::applicationDidFinishLaunching() {
...
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
        glview = GLViewImpl::createWithRect("test", cocos2d::Rect(0, 0, workingResolutionSize.width, workingResolutionSize.height));
#else
        glview = GLViewImpl::create("test");
#endif
...
}

As you can see I defined a resolution as half the size of 1080p and when I working with the game the window size satisfy me well.

But then I found the contentSize or boundingBox size will not keep the same as the raw image

To test that, I made a rectangle block 100x100 pixels, and loaded it and tested it as flowing (not sure whether it’s plist that to blame, so I made test both with plist and with raw image)

    this->cache = SpriteFrameCache::getInstance();
	this->cache->addSpriteFramesWithFile("plist/texture.plist");

	auto test100 = Sprite::createWithSpriteFrameName("test100.png");

	auto test100raw = Sprite::create("image/test100.png");

	test100->setAnchorPoint(Vec2(0, 0));
	CCLOG("visualbe size is (%f, %f)", Director::getInstance()->getVisibleSize().width, Director::getInstance()->getVisibleSize().height);
	
	CCLOG("test100 size bound (%f,%f)", test100->getBoundingBox().size.width, test100->getBoundingBox().size.height);
	CCLOG("test100 content size (%f,%f)", test100->getContentSize().width, test100->getContentSize().height);

	CCLOG("test100raw size bound (%f,%f)", test100raw->getBoundingBox().size.width, test100raw->getBoundingBox().size.height);
	CCLOG("test100raw content size (%f,%f)", test100raw->getContentSize().width, test100raw->getContentSize().height);

And the output of the log is as following:

    visualbe size is (1920.000000, 1080.000000)
    test100 size bound (187.499985,187.499985)
    test100 content size (187.499985,187.499985)
    test100raw size bound (187.499985,187.499985)
    test100raw content size (187.499985,187.499985)

To make things clear, I will upload the property inspector screenshot of the raw image(same one in plist as well as raw image) here:

And I really don’t know why this happens, and totally confused.

Could some one explain why the content size is almost 2 times scaled and more over why it’s not an even 200x200 instead of 187.???x187.??? ?

Hi.
based on your design resolution and resolution policy and device resolution you have a scaleFactor.
The content size of sprites are not image size in pixel but multiply by scale factor.

Hi @armnotstrong

Please show me the whole AppDelegate.cpp.

#include "AppDelegate.h"
#include "HelloWorldScene.h"

// #define USE_AUDIO_ENGINE 1
// #define USE_SIMPLE_AUDIO_ENGINE 1

#if USE_AUDIO_ENGINE && USE_SIMPLE_AUDIO_ENGINE
#error "Don't use AudioEngine and SimpleAudioEngine at the same time. Please just select one in your game!"
#endif

#if USE_AUDIO_ENGINE
#include "audio/include/AudioEngine.h"
using namespace cocos2d::experimental;
#elif USE_SIMPLE_AUDIO_ENGINE
#include "audio/include/SimpleAudioEngine.h"
using namespace CocosDenshion;
#endif

USING_NS_CC;

static cocos2d::Size designResolutionSize = cocos2d::Size(1920, 1080);
static cocos2d::Size workingResolutionSize = cocos2d::Size(1920 * 0.5, 1080 * 0.5); 
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 320);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);

AppDelegate::AppDelegate()
{
}

AppDelegate::~AppDelegate() 
{
#if USE_AUDIO_ENGINE
    AudioEngine::end();
#elif USE_SIMPLE_AUDIO_ENGINE
    SimpleAudioEngine::end();
#endif
}

// if you want a different context, modify the value of glContextAttrs
// it will affect all platforms
void AppDelegate::initGLContextAttrs()
{
    // set OpenGL context attributes: red,green,blue,alpha,depth,stencil
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};

    GLView::setGLContextAttrs(glContextAttrs);
}

// if you want to use the package manager to install more packages,  
// don't modify or remove this function
static int register_all_packages()
{
    return 0; //flag for packages manager
}

bool AppDelegate::applicationDidFinishLaunching() {
    // initialize director
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
        glview = GLViewImpl::createWithRect("test", cocos2d::Rect(0, 0, workingResolutionSize.width, workingResolutionSize.height));
#else
        glview = GLViewImpl::create("test");
#endif
        director->setOpenGLView(glview);
    }

    // turn on display FPS
    director->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    director->setAnimationInterval(1.0f / 60);

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
    auto frameSize = glview->getFrameSize();
    // if the frame's height is larger than the height of medium size.
    if (frameSize.height > mediumResolutionSize.height)
    {        
        director->setContentScaleFactor(MIN(largeResolutionSize.height/designResolutionSize.height, largeResolutionSize.width/designResolutionSize.width));
    }
    // if the frame's height is larger than the height of small size.
    else if (frameSize.height > smallResolutionSize.height)
    {        
        director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
    }
    // if the frame's height is smaller than the height of medium size.
    else
    {        
        director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
    }

    register_all_packages();

    // create a scene. it's an autorelease object
    auto scene = HelloWorld::createScene();

    // run
    director->runWithScene(scene);

    return true;
}

// This function will be called when the app is inactive. Note, when receiving a phone call it is invoked.
void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

#if USE_AUDIO_ENGINE
    AudioEngine::pauseAll();
#elif USE_SIMPLE_AUDIO_ENGINE
    SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
    SimpleAudioEngine::getInstance()->pauseAllEffects();
#endif
}

// this function will be called when the app is active again
void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();

#if USE_AUDIO_ENGINE
    AudioEngine::resumeAll();
#elif USE_SIMPLE_AUDIO_ENGINE
    SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
    SimpleAudioEngine::getInstance()->resumeAllEffects();
#endif
}

Well, the content size is the size of the image / content scale factor.
And the bounding box is rect with size equal content size but after applying some transform. (see CCNode.cpp)

When running on a PC, frameSize is equal to the size of glview. Therefore, your content scale factor is

MIN(1024 / 1920, 768 / 1080) = 0.533333

And your content size width (height) = 100 / 0.533333 = 187.50001171


I think that the standard AppDelegate.cpp does not illustrate the multi resolution support too well. And it should always be set according to the needs of your particular project. You can use the search on this forum for more information, or wait a bit, as I am about to finish the tutorial about it next week.

2 Likes

So, the simplest thing I have to do is to delete those code that set the content scale factor, right?

Have done that and now things work as expected.

Thanks!

Right. :slight_smile:
This will work for you during development. But I recommend you to use several resource folders and a setContentScaleFactor in the release version of your project.

@brightInverse Can you explain, why you would recommend the setContentScaleFactor and different resource folders in release? Where is the main difference/advantage between with/without it? I also removed it in my testing project, because I also didn’t see any advantage in it.

  • The first reason is the stability and performance.

Suppose that all of your graphics are designed for 1920x1080 (or better 2560x1440) resolution. It will work well and look good on devices with the same or similar screen. But if you run the game on a device with a much smaller screen and less RAM, you will get less performance than if you were using resources with less resolution.
And there is a possibility that this particular GPU does not support this resolution and in this case you get a black screen or crash.

  • The second reason is the quality.

If you use specialized graphics programs to scale resources, then the final picture will be better than if the cocos2d-x has scaled it for you.
Of course the engine will still use the scaling due to the ResolutionPolicy, but if you use multiple resource sets, the quality will still be better since the engine does not need to scale resources several times (x4, x6, x8…).

Let me know if you have any questions.

Would you prefer a large or low design resolution while developing or depends it on the type of game? Sorry, for my “noob” question, but I never used multiple assets yet.

This is a good question really.

This is a personal preference - how low or large your Design Resolution is.
It is important to choose the right Aspect ratio of Design Resolution according to the needs of your project. Then you can choose any resolution with this Aspect ratio as your Design Resolution.

Then you choose several Resource Resolutions (the resolutions for which you draw your resources).
You choose them depending on the Aspect ratio of your Design Resolution and ResolutionPolicy, and also on what screen resolutions are relevant at the moment (what devices are sold in stores).
Usually it is convenient if Design Resolution equal to one of the Resource Resolutions.

In my last project I use
Resource Resolutions - 1920x2560, 960x1280, 480x640;
Design Resolution - 480x640 (just because I prefer to work with a lower resolution, but any resolution with the same aspect ratio will work).

Then I just need to choose the right resource folder (depending on the Screen Resolution of the particular device) and set the right ContentScaleFactor (depending on what folder I chose, in my case it is 1, 2 or 3).
And then I work like I have only one folder with resources and only one resolution - my Design Resolution.


I try to explain this more clearly by the examples in my tutorial, but I am still working on illustrations right now ((.

1 Like