contentScaleFactor not working correctly

Cocos2dx version - 3.15.1
System - Windows 7 SP1 64 Bit

static cocos2d::Size designResolutionSize = cocos2d::Size(1280, 720);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 360);
static cocos2d::Size mediumResolutionSize = cocos2d::Size(1024, 768);
static cocos2d::Size largeResolutionSize = cocos2d::Size(2048, 1536);

My Image Size - 1280 * 720 (Background Image)

Results testing on 1920 * 1080 Device -
Content Scale Factor: 1.600000
FrameSize HW: 1080.000000 1920.000000 (getFrameSize)
Bounding HW= 450.000000 800.000000 (getBoundingBox)
Image HW= 450.000000 800.000000 (getContentSize)

Results testing on 800 * 480 Emulator -
Content Scale Factor: 0.800000
FrameSize HW: 480.000000 800.000000
Bounding HW= 900.000000 1600.000000
Image HW= 900.000000 1600.000000

So basically, scaledSize = originalSize / contentScaleFactor.
But this should be scaledSize = originalSize * contentScaleFactor

Please help @nite @slackmoehrle @zhangxm

Yes. scaledSize = originalSize / contentScaleFactor.
Assume you have an image with 100x100 pixel. In lower resolution you need 50x50 version of this image so content scale factor is equal to 0.5, but in drawing this image you need scale it to 2x.
content scale factor = low res content size / original (maybe high res) res content size.

What I want to do is. I want to fit my background image (1280 * 720) to both higher (by scaling up) and lower (by scaling down) resolution screens i.e

Example -
Design Res - 1280 * 720
Large Device Res - 1920 * 1080
AR = 1.77
Scale Factor = 1920 / 1280 = 1.5
So, my Image Height = 720 * 1.5 = 1080 and Width = 1280 * 1.5 = 1920

Now,
Design Res - 1280 * 720
Large Device Res - 800 * 480
AR = 1.66
Scale Factor = 800 / 1280 = .625, 480 / 720 = .667 (Taking the big one)
So, my Image Height = 720 * .667= 480.24 and Width = 1280 * .667 = 853.76

How can I achieve this using setContentScaleFactor?

Can you show some real code?

I will explain few Test Cases with my files and snapshots of my device and emulator with required outputs.
Original Image Size - 1280 * 720

Test Case 1:

This case is by default. No changes made.

AppDelegate.cpp

#include "AppDelegate.h"
#include "SplashScreen.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(1280, 720);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 360);
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("IndianPolityWar", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
        glview = GLViewImpl::create("IndianPolityWar");
#endif
        director->setOpenGLView(glview);
    }

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

    // 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));
    }
    else if (frameSize.height > smallResolutionSize.height)
    {
        director->setContentScaleFactor(MIN(mediumResolutionSize.height/designResolutionSize.height, mediumResolutionSize.width/designResolutionSize.width));
    }
    else
    {
        director->setContentScaleFactor(MIN(smallResolutionSize.height/designResolutionSize.height, smallResolutionSize.width/designResolutionSize.width));
    }

    register_all_packages();

    //Logging
    int dpi = Device::getDPI();
    CCLOG("dpi = %d", dpi);
    CCLOG("Content Scale Factor: %f", director->getContentScaleFactor());
    CCLOG("FrameSize HW: %f %f", frameSize.height, frameSize.width);

    // create a scene. it's an autorelease object
    auto scene = SplashScreen::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
}

SplashScreen.cpp

#include "SplashScreen.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;

Scene* SplashScreen::createScene()
{
    return SplashScreen::create();
}

bool SplashScreen::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto sprite = Sprite::create("images/splashscreen.png");    
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    sprite->setOpacity(0);
    this->addChild(sprite, 0);

    auto fadeIn = FadeIn::create(0.5f);
    sprite->runAction(fadeIn);

    //Logging
    CCLOG("Bounding HW= %f %f", sprite->getBoundingBox().size.height, sprite->getBoundingBox().size.width);
    CCLOG("Image HW= %f %f", sprite->getContentSize().height, sprite->getContentSize().width);

    return true;
}

Output:

For, 480 * 800 Emulator:

dpi = 240
Content Scale Factor: 0.800000
FrameSize HW: 480.000000 800.000000 (getFrameSize)
Bounding HW= 900.000000 1600.000000 (getBoundingBox)
Image HW= 900.000000 1600.000000 (getContentSize)

testcase_1_480_800

For, 1920 * 1080 Device:

dpi = 480
Content Scale Factor: 1.600000
FrameSize HW: 1080.000000 1920.000000
Bounding HW= 450.000000 800.000000
Image HW= 450.000000 800.000000

This is the case, I explained in my question.

Test Case 2:

Here I have removed all setContentScaleFactor coding block from AppDelegate.cpp.

AppDelegate.cpp

#include "AppDelegate.h"
#include "SplashScreen.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(1280, 720);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 360);
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("IndianPolityWar", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
        glview = GLViewImpl::create("IndianPolityWar");
#endif
        director->setOpenGLView(glview);
    }

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

    // 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();

    register_all_packages();

    //Logging
    int dpi = Device::getDPI();
    CCLOG("dpi = %d", dpi);
    CCLOG("Content Scale Factor: %f", director->getContentScaleFactor());
    CCLOG("FrameSize HW: %f %f", frameSize.height, frameSize.width);

    // create a scene. it's an autorelease object
    auto scene = SplashScreen::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
}

SplashScreen.cpp

#include "SplashScreen.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;

Scene* SplashScreen::createScene()
{
    return SplashScreen::create();
}

bool SplashScreen::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto sprite = Sprite::create("images/splashscreen.png");
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    sprite->setOpacity(0);
    this->addChild(sprite, 0);

    auto fadeIn = FadeIn::create(0.5f);
    sprite->runAction(fadeIn);

    //Logging
    CCLOG("Bounding HW= %f %f", sprite->getBoundingBox().size.height, sprite->getBoundingBox().size.width);
    CCLOG("Image HW= %f %f", sprite->getContentSize().height, sprite->getContentSize().width);

    return true;
}

Output:

For, 480 * 800 Emulator:

dpi = 240
Content Scale Factor: 1.000000
FrameSize HW: 480.000000 800.000000
Bounding HW= 720.000000 1280.000000
Image HW= 720.000000 1280.000000

testcase_2_480_800

For, 1920 * 1080 Device:

dpi = 480
Content Scale Factor: 1.000000
FrameSize HW: 1080.000000 1920.000000
Bounding HW= 720.000000 1280.000000
Image HW= 720.000000 1280.000000

As here you can see, though the image is correctly fit, but according to screen size, image size is wrong.
For, 480 * 800 device, it’s image size is 720 * 1280. But it should be 480 * 800. Also the same is happening for 1920 * 1080 device.

Test Case 3:

Here I am removing removing all the setContentScaleFactor block from AppDelegate.cpp and adding my own scaling class Utils.cpp. Then trying to scale my image from SplashScreen.cpp.

AppDelegate.cpp

#include "AppDelegate.h"
#include "SplashScreen.h"
#include "Utils.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(1280, 720);
static cocos2d::Size smallResolutionSize = cocos2d::Size(480, 360);
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("IndianPolityWar", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
        glview = GLViewImpl::create("IndianPolityWar");
#endif
        director->setOpenGLView(glview);
    }

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

    // 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();

    register_all_packages();

    //Logging
    int dpi = Device::getDPI();
    CCLOG("dpi = %d", dpi);
    CCLOG("Content Scale Factor: %f", director->getContentScaleFactor());
    CCLOG("FrameSize HW: %f %f", frameSize.height, frameSize.width);

    Utils::getWinSize(frameSize.height, frameSize.width);

    // create a scene. it's an autorelease object
    auto scene = SplashScreen::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
}

SplashScreen.cpp

#include "SplashScreen.h"
#include "SimpleAudioEngine.h"
#include "Utils.h"

USING_NS_CC;

Scene* SplashScreen::createScene()
{
    return SplashScreen::create();
}

bool SplashScreen::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto sprite = Sprite::create("images/splashscreen.png");
    Utils::scaleBG(sprite);
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    sprite->setOpacity(0);
    this->addChild(sprite, 0);

    auto fadeIn = FadeIn::create(0.5f);
    sprite->runAction(fadeIn);

    //Logging
    CCLOG("Bounding HW= %f %f", sprite->getBoundingBox().size.height, sprite->getBoundingBox().size.width);
    CCLOG("Image HW= %f %f", sprite->getContentSize().height, sprite->getContentSize().width);

    return true;
}

Utils.cpp

#include "Utils.h"

using namespace cocos2d;

static float designScreenHeight = 720;
static float designScreenWidth = 1280;
float screenHeight = 720;
float screenWidth = 1280;

void Utils::scaleBG(cocos2d::Sprite *bg) {
    float scaleX = 1;
    float scaleY = 1;

    if((screenWidth / screenHeight) > (designScreenWidth / designScreenHeight)) {
        scaleX = screenWidth / designScreenWidth;

        bg->setScale(scaleX);
    } else {
        scaleY = screenHeight / designScreenHeight;

        bg->setScale(scaleY);
    }

    CCLOG("Utils: screenHeight, screenWidth: %f, %f", screenHeight, screenWidth);
    CCLOG("Utils: designScreenHeight, designScreenWidth: %f, %f", designScreenHeight, designScreenWidth);
    CCLOG("Utils: scaleX, scaleY: %f, %f", scaleX, scaleY);
}

void Utils::getWinSize(float height, float width) {
    screenHeight = height;
    screenWidth = width;
}

Output:

On, 480 * 800 Emulator:

dpi = 240
Content Scale Factor: 1.000000
FrameSize HW: 480.000000 800.000000
Utils: screenHeight, screenWidth: 480.000000, 800.000000
Utils: designScreenHeight, designScreenWidth: 720.000000, 1280.000000
Utils: scaleX, scaleY: 1.000000, 0.666667
Bounding HW= 480.000000 853.333313
Image HW= 720.000000 1280.000000

testcase_3_480_800

On, 1920 * 1080 Device:

dpi = 480
Content Scale Factor: 1.000000
FrameSize HW: 1080.000000 1920.000000
Utils: screenHeight, screenWidth: 1080.000000, 1920.000000
Utils: designScreenHeight, designScreenWidth: 720.000000, 1280.000000
Utils: scaleX, scaleY: 1.000000, 1.500000
Bounding HW= 1080.000000 1920.000000
Image HW= 720.000000 1280.000000

Now, here what I don’t understand is, though bounding box dimensions are showing correct values, why image height, width is not showing correct? Also, here Image is not showing correctly according to their height, width.

We should definitely cover this in the new docs. Can I use your screenshots? Let me look at your code and get it in a project that I can run and test.

Yes of course. Please solve this as soon as possible. :slight_smile:

Any updates?

@zhangxm Do you see anything here?

@stevetranby @grimfate can probably help us understand too. For me, I don’t use contentScaleFactor in this same way. I decide the scale factor myself and then using it as a multiplier when positioning, scaling, etc.

As you can see from Test Case 2, then even if the image is getting properly fit in the screen, the dimension of image is not correct. When a 1280 * 720 image is getting perfectly fitted into a 1920 * 1080 screen, the image’s dimension should also become 1920 * 1080. Right? But it is not happening in my case.

Also from Test Case 3, you can see that, Bounding Box dimensions are correct but image HW is not correct.

I don’t know what to do now. I have ideas of 2 games, and it’s all stopped now.

Don’t use getFrameSize. You don’t need it actually. Maybe only when deciding on which size of device is smaller.
Use Director::getInstance()->getVisibleSize(); instead.

On your answer, I would like to post another Test Case.

Cocos2d-x: 3.16
NDK: r14b
Android Studio: 2.3.3
OS: Windows 7 Ultimate SP1 64 bit

Test Case 4:

Here,

  • I have removed all the pre-written setContentScaleFactor and added mine.

  • No custom Utils.cpp

AppDelegate.cpp

#include "AppDelegate.h"
#include "SplashScreen.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(1280, 720);
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
}


void AppDelegate::initGLContextAttrs()
{
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};

    GLView::setGLContextAttrs(glContextAttrs);
}

static int register_all_packages()
{
    return 0;
}

bool AppDelegate::applicationDidFinishLaunching() {
    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("IPW", cocos2d::Rect(0, 0, designResolutionSize.width, designResolutionSize.height));
#else
        glview = GLViewImpl::create("IPW");
#endif
        director->setOpenGLView(glview);
    }

    director->setDisplayStats(false);
    director->setAnimationInterval(1.0f / 60);

    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
    auto frameSize = glview->getFrameSize();

    float scale = MIN(director->getVisibleSize().height/designResolutionSize.height, director->getVisibleSize().width/designResolutionSize.width);
    director->setContentScaleFactor(1/scale);

    register_all_packages();

    int dpi = Device::getDPI();
    CCLOG("dpi = %d", dpi);
    CCLOG("Content Scale Factor: %f", director->getContentScaleFactor());
    CCLOG("FrameSize HW: %f %f", frameSize.height, frameSize.width);
    CCLOG("VisibleSize HW: %f %f", director->getVisibleSize().height, director->getVisibleSize().width);

    auto scene = SplashScreen::createScene();
    director->runWithScene(scene);

    return true;
}

void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

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

void AppDelegate::applicationWillEnterForeground() {
    Director::getInstance()->startAnimation();

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

SplashScreen.cpp

#include "SplashScreen.h"
#include "SimpleAudioEngine.h"

USING_NS_CC;

Scene* SplashScreen::createScene()
{
    return SplashScreen::create();
}

bool SplashScreen::init()
{
    if ( !Scene::init() )
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    auto sprite = Sprite::create("images/splashscreen.png");
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    sprite->setOpacity(0);
    this->addChild(sprite, 0);

    auto fadeIn = FadeIn::create(0.5f);
    sprite->runAction(fadeIn);

    //Logging
    CCLOG("Bounding HW= %f %f", sprite->getBoundingBox().size.height, sprite->getBoundingBox().size.width);
    CCLOG("Image HW= %f %f", sprite->getContentSize().height, sprite->getContentSize().width);

    return true;
}

Output:

On my 480 * 800 Emulator:

dpi = 240
Content Scale Factor: 1.066667
FrameSize HW: 480.000000 800.000000
VisibleSize HW: 720.000000 1200.000000
Bounding HW= 675.000000 1200.000000
Image HW= 674.999939 1199.999878

testcase_4_480_800

As you can see again that though the image is fitted perfectly but the dimensions are wrong. Image dimension should be here 480 * 800.

On my 1920 * 1280 device:

dpi = 480
Content Scale Factor: 1.000000
FrameSize HW: 1080.000000 1920.000000
VisibleSize HW: 720.000000 1280.000000
Bounding HW= 720.000000 1280.000000
Image HW= 720.000000 1280.000000

As you can see here too that o a 1920 * 1080 device, the fully fitted image’s dimension is showing 1280 * 720.

That’s what my problem is. Though the image is fully fitted into the screen, why it’s dimensions are different?

Okay.
Original Image Size - 1280 x 720
scale factor = 1,
that means ONE PHYSICAL PIXEL of your image = ONE DESIGN UNIT in cocos2dx
So your image size in design units (points) = 1280 x 720

1 Like

Yes, I understand that. But how can it perfectly fit in 1920 * 1080 resolution? Should not it’s dimension become 1920 * 1080 then?

Not an expert here, but could it be because designResolutionSize is set to 1280x720? Pretty sure that is what determines what resolution cocos considers “full screen” to be.

Design resolution set to 1280 x 720.
So the whole screen is 1280 x 720

If device has another ratio there could be some cropping happening.
See here:
http://www.cocos2d-x.org/wiki/Multi_resolution_support

I recommend to try out Fixed Height and Fixed Width resolution policies.

@ivcoder @grimfate
I want my design graphics to be only one set. I want to design based on 1280 * 720 resolution so that it can scale to both high and low resolution. Please suggest me what to do. I will also update your suggested test cases.