iPhone 5 Stretching

Hello,

First off let me say that I really like the multiresolution system that cocos2dx (v2.0) offers. I have successful got my game working on iPadHD, iPad, iPhone retina (960x640), and iPhone resolutions without any stretching or graphical artifacts. Unfortunately when it comes to testing on iPhone 5 I get two senarios happen. When I try to treat it like an iphone 4s (960x640) resolution I get the screen to fill up but it gets cropped on the edges. And when I try to conform to the 640x1136 resolution I get stretching. For my project I made all my raw assets in photoshop at the iPadHD scale (2048x1536). Then inside texturepacker I create sprite sheets for iPadHD, iPad, and iPhone sizes. These sprite sheets are exported at their respective scales of the original iPadHD. So for example the sprite sheet for iPadHD is 1.0, iPad is 0.5, and iPhone is 0.234375. For the iPhone retina (960x640) I use the iPad (728x1024) sprite sheet I find that it works without any graphical issues. Next for menu layouts I use cocosbuilder and in there I have double check that I am using percent based coordinated and sizes. Here is the code for setting up my resolutions:

CCSize designSize = CCSizeMake(320, 480);
    if(screenSize.height > 1024)
    {
        // iPhone 5 (640x1136)
        if(screenSize.width < 1536)     
        {
            CCSize designSize = CCSizeMake(320, 568);
            CCSize resourceSize = CCSizeMake(768, 1024);
            CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
            pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
        }
        // iPadHD (1536x2048)
        else
        {
            designSize = CCSizeMake(1536, 2048);
            CCSize resourceSize = CCSizeMake(1536, 2048);
            CCFileUtils::sharedFileUtils()->setResourceDirectory("ipadhd");
            pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
        }
    }
    // iPad (768x1024)
    else if (screenSize.height > 960)
    {
        designSize = CCSizeMake(768, 1024);
        CCSize resourceSize = CCSizeMake(768, 1024);
        CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
        pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
    }
    // iPhoneHD (640x960)
    else if (screenSize.height > 480)
    {
        CCSize resourceSize = CCSizeMake(768, 1024);
        CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
        pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
    }
    // iPhone (320x480)
    else
    {
        CCSize resourceSize = CCSizeMake(360, 480);
        pDirector->setContentScaleFactor(resourceSize.width/ designSize.width);
        CCFileUtils::sharedFileUtils()->setResourceDirectory("iphone");
    }

Any suggestions what I can do to fix the stretching in iPhone 5 would be great. Thanks!

You might want to play with CCEGLView::setDesignResolutionSize*
In cocos2d-x-2.0.4 AppDelegate.cpp file, you can find
pEGLView -> setDesignResolutionSize( smallResource.size.width, smallResource.size.height, kResolutionNoBorder )* somewhere there. Try replacing kResolutionNoBorder with kResolutionExactFit or kResolutionShowAll

From experiences, I learned that kResolutionExactFit will stretch all your assets to fit the screen.

Thanks for your reply Lance. Actually I left that part out I am doing this right after the code above:

CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder);

I think I need to keep the kResolutionNoBorder policy because if I pick others it will mess with the placement of the HUD in game.

Thanks

kResolutionNoBorder will ( obviously ) remove all borders in the view.

From your code, this part is what seems to be the problem. You’re using iPad resources for the iPhone 5.
I believe using iPhone HD resources for iPhone 5 would be the best way to go about it.

        // iPhone 5 (640x1136)
        if(screenSize.width < 1536)        
        {
            CCSize designSize = CCSizeMake(320, 568);      // This part right here.
            CCSize resourceSize = CCSizeMake(768, 1024);
            CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
            pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
        }

Hey Lance, So I went ahead and made those modifications as you suggested. I made a new folder called if iphonehd and made a spritesheet for using TexturePacker. This sprite sheet is 0.41667 the size of the iPadHD sprite sheet (640/1536=0.41666666667).

I tried this:

// iPhone 5 (640x1136)
if(screenSize.width < 1536)     
{
    CCSize designSize = CCSizeMake(640, 1136);
    CCSize resourceSize = CCSizeMake(640, 1136);
    CCFileUtils::sharedFileUtils()->setResourceDirectory("iphonehd");
    pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
}

What this ends up doing is making the content scale factor of the game being 1.0 and because of this I get some weird artifacts check out the screen shot (artifacts.png). Changing the policy (kResolutionNoBorder -> kResolutionExactFit) did not remedy the artifacts but it did make it all fit inside the border.

(artifacts.PNG - http://www.jakubl.com/artifacts.PNG)

Now with this modification:

// iPhone 5 (640x1136)
if(screenSize.width < 1536)     
{
    CCSize designSize = CCSizeMake(320, 568);
    CCSize resourceSize = CCSizeMake(640, 1136);
    CCFileUtils::sharedFileUtils()->setResourceDirectory("iphonehd");
    pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
}

The content scale factor is 2.00 and everything looks great except for the fact that its cut off on the edges. Changing the policy from kResolutionNoBorder to kResolutionExactFit will fix the issue of the sides being cropped but then I get the issue again of stretching. I have included screenshots of this (resolutionnoborder.png and resolutionexactfit.png).

(resolutionnoborder.png - http://www.jakubl.com/resolutionnoborder.png)

(resolutionexactfit.png - http://www.jakubl.com/resolutionexactfit.png)

Lastly for comperison I have included a screenshot of what it should look like on a iPhone 4s (640x960.png).

(640x960.png - http://www.jakubl.com/640x960.png)

Thanks again for your suggestions I feel like part of the problem is that the iphone 5 is an awkward resolution out of the other devices.

EDIT: Sorry I should have scaled these images down a little.

Ok, I figured it out so I guess I’ll share my findings if anyone else stumbles into this issue. So the code that I originally posted was good and ended up working. The modifications that I ended up doing were inside the cocosbuilder tool. Instead of using the control buttons for all of my game buttons which ended up getting stretched in iphone 5 resolution I switched and used the CCMenuItemImage button.

Thanks again Lance for your help.

This chunk of code:

// iPhone 5 (640x1136)
if(screenSize.width < 1536)        
{
    CCSize designSize = CCSizeMake(640, 1136);
    CCSize resourceSize = CCSizeMake(640, 1136);
    CCFileUtils::sharedFileUtils()->setResourceDirectory("iphonehd");
    pDirector->setContentScaleFactor(resourceSize.width/designSize.width);
}

What this does is to set the contentScaleFactor depending on your resource size versus relative to your design size.

resourceSize is the sizes of which your resources are based on. For example, you could have a button that has a size of 100 x 100 on iPhone and 120 x 120 on iPad. 100x100 and 120x120 is the actual resource size and the resourceSize is 480x320 and 1024x768 respectively.

designSize, on the other hand, is the size in which you based all your screens upon. For example, you have this thing called a “wireframe” layout where you would base all the locations and the likes. This “wireframe” is the designSize.

What I usually do is to have a separate check for iOS and Android devices, so that the resources to be used will strictly be the ipad and iphone version while the Android version would depend on screen size to select which resource to use.

The bottom line is, I was trying to get help with is getting a perfectly square button in all device resolutions. In my case the game center button is a perfect square 193x193 on ipadHD resolution. Converting this to a percentage system works to scale in ALL device resolution (320x480, 640x960, 768x1024, 1536x2048) EXCEPT the iphone 5 resolution where the square gets stretched vertically if in portrait mode or horizontally in landscape mode. Even creating a square button in the TestCPP cocosbuilder project I get the same result in iphone 5 resolutions.

Now like in my previous post I mentioned that I found that you can remedy this by using the CCMenuImageItem.

First of all, I’m happy I’m not the only person with this problem on iphone5 :smiley:

So, on iphone5 everything is scaled and my UI is not shown properly and sometimes is even cropped.

Related to following link: [[http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Multi_resolution_support]]

“When using NoBorder mode, there are some areas of the background out of scope. If you use absolute coordinates based on design resolution size,
some of your game UI will not be shown completely.
To resolve this issue, you have to make the coordinates base on ‘visible rectangle’. You can get the origin point of ‘visible rectange’ by ’CCDirector::sharedDirector()>getVisibleOrign’.
Together with ’CCDirector::sharedDirector
>getVisibleSize‘,you will be able to confirm 9 points on the screen. They are ’Left’,‘Right’, ‘Top’,‘Bottom’,‘Center’,‘LeftTop’,‘RightTop’,‘LeftBottom’ and ‘RightBottom’.
Your game will be really full screen display if all the coordinates of your game is base on these nine points.
About how to calculate these points, please refer to ‘VisibleRect’ class in TestCpp project."
It seems to have the key to solve it, but I didn’t get the point of it :;@
and if it is iphone4/4s
designResolutionSize = cocos2d::CCSizeMake(480, 320);
I saw you did quite the same, so I don’t feel as crazy as before.
However,
~~ it works for CCScale9Sprite ,
~~ CCSprites are scaled (expected behavior after read how it works with ResolutionNoBorder policy)

  • CCControlButtons are scaled and even get weird shapes
  • So Im using CCMenuItemImage which doesnt have this weird behavior, but now I didnt have”Zoom on touch down" :frowning:

Which was you final solution about all this resolution mess?

thx

Have you tried using relative position instead of absolute?
Also, you should do a bit of math to position stuff on the screen if you are using the new multi-resolution system.

Something like this:

CCSize screenSize = CCDirector::sharedDirector() -> getVisibleSize();
CCPoint screenOrigin = CCDirector::sharedDirector() -> getVisibleOrigin();

float xPos = screenOrigin.x + ( screenSize.width / 2 );   // Center of screen, horizontally
float yPos = screenOrigin.y + 100;                        // 100 pixels from bottom

sprite -> setPosition( CCPointMake( xPos, yPos ) );

Finally, what I did and it works in all devices is setting applicationDidFinishLaunching like this:

bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
CCDirector* pDirector = CCDirector::sharedDirector();
CCEGLView* pEGLView = CCEGLView::sharedOpenGLView();
>
pDirector->setOpenGLView(pEGLView);
>
// IMPORTANT LINE!
*CCSize size = CCDirector::sharedDirector()>getWinSizeInPixels*
>
// Set the design resolution
**pEGLView
>setDesignResolutionSize;*
>
CCSize frameSize = CCEGLView::sharedOpenGLView~~>getFrameSize;
>
// if the frame’s height is larger than the height of medium resource size, select large resource.
if
{
CCFileUtils::sharedFileUtils~~>setResourceDirectory;
*pDirector~~>setContentScaleFactor;*
}
// if the frame’s height is smaller than the height of medium resource size, select small resource.
else
{
CCFileUtils::sharedFileUtils~~>setResourceDirectory;
*pDirector~~>setContentScaleFactor;*
}
>
// turn on display FPS
pDirector~~>setDisplayStats;
>
// set FPS. the default value is 1.0/60 if you don’t call this
pDirector~~>setAnimationInterval;
>
// create a scene. it’s an autorelease object
CCScene**pScene = HelloWorld::scene;
>
// run
pDirector~~>runWithScene(pScene);
>
return true;
}

ContentScaleFactor is directly calculated from real device size in pixels. So it is not even required to define default design resolution size.