VisibleSize not the same as size of display?

Hi again!
Why is my visible size not correct?

CCLOG("visiablesize x: %f y: %f", visibleSize.width + origin.x, visibleSize.height + origin.y);

Output:
visiablesize x: 453.333313 y: 320.000000
2016-04-15 15:15:32.311 TMXer-mobile[912:133289] cocos2d: surface size: 1024x768

Resolution policy: NO_BORDER

Thank you

Show the code

AppDelegate:

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

USING_NS_CC;

static cocos2d::Size designResolutionSize = cocos2d::Size(480, 320);
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 you want a different context,just modify the value of glContextAttrs
//it will takes effect on all platforms
void AppDelegate::initGLContextAttrs()
{
    //set OpenGL context attributions,now can only set six attributions:
    //red,green,blue,alpha,depth,stencil
    GLContextAttrs glContextAttrs = {8, 8, 8, 8, 24, 8};

    GLView::setGLContextAttrs(glContextAttrs);
}

// If you want to use packages 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) {
        glview = GLViewImpl::create("My Game");
        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.0 / 60);

    // Set the design resolution
    glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
    Size 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. When comes a phone call,it's be invoked too
void AppDelegate::applicationDidEnterBackground() {
    Director::getInstance()->stopAnimation();

    // if you use SimpleAudioEngine, it must be pause
    // SimpleAudioEngine::getInstance()->pauseBackgroundMusic();
}

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

    // if you use SimpleAudioEngine, it must resume here
    // SimpleAudioEngine::getInstance()->resumeBackgroundMusic();
}


HelloWorld:

bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    CCLOG("visiablesize x: %f y: %f", visibleSize.width + origin.x, visibleSize.height + origin.y);

Director::getVisibleSize() usually returns the design resolution.

Design resolution is used as a constant space on all devices which is transformed to fit the screenā€™s pixels based on a policy. Design resolution could have been implemented in a normalized range of 0->1, but by using an arbitrary range developers and easily map their layouts to asset sizes. A content scale factor is then used to bring higher/lower resolution assets into design resolution space.

In the case of ResolutionPolicy::NO_BORDER then Size(_screenSize.width/_scaleX, _screenSize.height/_scaleY) is returned. Where _scaleX and _scaleY equal the max ratio between design resolution and screen size.

For more detailed information see implementations of GLView::getVisibleSize() and GLView::updateDesignResolutionSize().

If you want window size then use Director::getWinSize() or Director::getWinSizeInPixels().

Hope this helps.

Thanks I really appreciate that answer! But usually visiblesize return the same as resolution - For instance on my ipad 2 it returns 1024x768 and the surface size is the exact same but with this project they arenā€™t the sameā€¦Just think that is strange now where they both have the same resolution policy.

Same policy but do both projects use the same design resolution? (see top of your AppDelegate.cpp file). The policy only defines how design resolution will be scaled to fit the screen.

1 Like

You seem good at this - So do you know why they set the default design resolution to 480, 320 no matter the screen instead of just doing this like a lot of projects you can download use:

bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    CCEGLView* pEglView = CCEGLView::sharedOpenGLView();
    
    pDirector->setOpenGLView(pEglView);
    
    // Set resolution size and paths
    pEglView->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, kResolutionNoBorder);
    CCSize frameSize = pEglView->getFrameSize();
    

Thanks!

Iā€™m not sure I understand the question, 480x320 is the resolution of the first generation iPhone and I suppose people use it because itā€™s a good base line as iOS typically scales in integer increments.

Personally I use 1280x720 as a design resolution as I find it easier to adapt 16:9 to 4:3 than the other way around.

Thanks Again.
But what I meant was - Why donā€™t you just set the design resolution to win size? Like on an ipad 4 the design resolution of 2048x1536 and so on for the other devices but where you instead have set a specific resolution of, in your case 1280x720?

Got me?

The design resolution is the resolution at which you created your sprites - so you design your game for (say) 1280 x 720 - what should you do if you play the game on a screen with a resolution of 480 x 320? Or 1280 x 1024?

You scale it in some way.
You could scale it so that it always shows all the pixels (with a possible ā€˜gapā€™ top and bottom or left and right (depending on the aspect ratio)
You could scale it so that the full width is always shown (so you could ā€˜loseā€™ some pixels top and bottom, or have a ā€˜gapā€™ top and bottom.
You could scale it so that the full height is always shown (so you could ā€˜loseā€™ some pixels left and right, or have a ā€˜gapā€™ left and right.
You could scale it so there is no ā€˜gapā€™, so you may ā€˜loseā€™ some pixels left and right and/or top and bottom.

So if you created a 1024x768 sprite and showed it screen centre on a 1024 x 768 screen, with a design resolution of 1024 x 768 then you donā€™t need to do anything - it all fits on a 1:1 scale.

Now run the same game on a 1280 x 720 screen.

What is it going to do. You set the design resolution to 1024 x 768 because thatā€™s what you designed your sprite at - so cocos knows to scale up to fit on the screen (depending on your requirements)

If you had the design resolution change to be 1280 x 720, your 1024 x 768 sprite now is expected to be 1024 x 768 and not the size of the screen (1280 x 720) - so it will look ā€˜tinyā€™ even though you wanted it to fill the screen.

Hope this helps - it is a really confusing subject - see the number of posts here about screen resolution! - and I find the more different people explain, at some point, you ā€œget itā€

Iā€™m personally just about getting there!

try reading through what is probably the longest thread on this site

2 Likes

Wow dude! Now it is clear to me. Thank you!!!

And ofc @almax27 Thanks for your time

O God . Shall I enter that thread ;(

Abandon all hope, ye who enter there :wink:

So Can you help me a wee bit more.

I want to make a game. Top down ā€œWipe Outā€ game. Simple control a vehicle top down.

How should I build it ?

Should I just make it using the design resolution ?
This seems to be what is the way to go right ?

Thanks

Seriously, if you want to support different screen sizes, you should read the link and understand it - experiment a bit and test on different resolutions (emulators are fine for this) until you understand whatā€™s required in your particular case.

If you ā€œjust make it using the design resolutionā€ then there are still decisions that may need to be made to support other resolutions - so Iā€™d create a test project and experiment until youā€™re comfortable.

1 Like

No shortcut then. Suppose ill have to enter that thread. God have mercy on my soul !

Thanks for the pep talk !

Honestly it took me ages to get my head around it - and I basically read all the stuff on here but it just wasnā€™t sinking in - so I wrote a simple ā€˜gameā€™ that put a sprite, that was a png at the design resolution, in the centre of the screen.
Then ran it at different design resolutions with different settings;
That shows the different ways it can be displayed:
e.g. for a design of 1024 x 768

  1. screen resolution = 1024 x 768 = ideal solution
  2. screen resolution = 512 x 394 = either just see middle of sprite or sprite is shrunk to fit, but then fits
  3. screen resolution = 2048 x 1536 - either see sprite in the middle of black area, or sprite is zoomed to fit, but then fits
  4. screen resolution = 2000 x 768 = Either black bars left and right or zoomed in and lose top and bottom
  5. screen resolution = 1024 x 900 = Either black bars top and bottom or zoomed in and lost left and right

You get the idea - once Iā€™d played with that, and played with the settings, I came up with a solution that suited me for my game (essentially I provide assets in 4 resolutions and use different assets depending on the device. The design resolution is slightly smaller that the highest screen resolution I expect to supportā€¦

Some snippets of code from my AppDelegate belowā€¦

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

ā€¦

// 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 ;
            CCLOG("Trying %s widthDiff %d ScaleFactor %.2f VisibleOffset %.0f, %.0f", found.directory, widthDiff, scaleFactor, director->getVisibleOrigin().x, director->getVisibleOrigin().y);
        }
    }
    
    
}
// 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);
1 Like