Problem with @2x CCSprite versions

Topics: iOS, Sprites and SpriteBatch
Oct 3, 2013 at 6:18 PM
Edited Oct 3, 2013 at 6:21 PM
Hi people

I'm developing a game (initially) for ios and try to figure out how to support retina and non-retina versions. I'm used to virtual coordinates from ios so I set
// in my ApplicationDidFinishLaunching: as in angry ninjas
CCDrawManager.SetDesignResolutionSize(320, 480, CCResolutionPolicy.ShowAll);
That seem to work well but I have a problem with hi-res ccsprites and sprite sheets.

CCTexture2D will load via CCContentManager -> XNA.ContentManager -> XNA.TitleContainer

It seems that the information that a hires image was used is lost after the TitleContainer opened the stream.

Thus when the sprite is rendered it is 4x to big. Because it's 2x the size and the scale factor is 2 because of the contentScale factor of the top UIView layer.

When I'm using standard CCSprites I can fix this by setting scaleFactor to 1/contentScale but this makes me wonder if I'm actually doing it the right way. At least this way the fallback to non hires does not work anymore.

Is there a better way to work resolution independent? Seems strange since every iOS developer will face this problem.

EDIT: The other thing I found strange is that angry ninjas is using the original cocos2d '-hd'-notation. But that does not seem to work at all since TitleContainer only checks for @2x. So when you run angry ninja on the retina simulator you see that all sprites are upscaled versions of non retina images.
Oct 7, 2013 at 6:34 AM
I logged a bug for this request. We've been working with our own content manager so this may be a bug that is fixed by using the cc2d-xna content manager.
Oct 7, 2013 at 2:10 PM
Great thanks.

The scaleFactor=1/contentScale hack works pretty well though.
So I don't have any real issues
Nov 11, 2013 at 10:33 PM
Seems that my problem is not a bug. I just didn't know that I have to set the content scale factor on CCDirector to make it work:
var height = CCDrawManager.FrameSize.Height;
if (height > 480)
    height /= 2;

CCDrawManager.SetDesignResolutionSize(320, height, CCResolutionPolicy.ShowAll);
CCDirector.SharedDirector.ContentScaleFactor = CCDrawManager.FrameSize.Width / CCDrawManager.DesignResolutionSize.Width;
Nov 12, 2013 at 2:51 AM
That still seems like a bug to me, so we'll keep the issue up on github.

The code you show is actually incorrect per cocos2d usage. Your design resolution is a static value since your assets are all designed around a single resolution target. Your halving the height when it is larger than 480 is a little hack that you should not need to do.

The @2x higher resolution assets should be properly scaled. Since that is not happening, it seems like a bug.
Jan 28, 2014 at 1:27 PM
Where can I see the upkeep on this issue on github?

I experience the same trouble and halving the height is not an option. For now I just set the scale to 0.5 for the images when it's on a retina.
Jan 28, 2014 at 1:30 PM
You're not halving the height (in terms of quality loss).

You are just setting the design resolution size. Just try it. You don't have to do anything else. Afterwards it behaves as expected
Jan 28, 2014 at 1:39 PM
Here's the reference (since cocos xna is derived from cocos-2dx even though it probably changed considerably in the meantime)
Jan 28, 2014 at 2:37 PM
I think i might be looking in the wrong direction.

It's the difference between iPad, iPad Retina and iPhone Retina and the @2x that get's me puzzled.

On iPad I add an image 280 x 203 with screen resolution 1024 x 768.
On iPad Retina the image@2x (560 x 406) get's loaded and screen resolution 2048 x 1536.
This looks both as expected. Because the ContentScaleFactor for the retina is 2.

But when I get to the iPhone Retina i get the image@2x (560 x 406) and a screen resolution of 960 x 640.
And here the image is double the size on screen because the ContentScaleFactor is only 0.9375.
This is normal behaviour for a machine, but not what i want.

Do I have to make a difference for iPhone or is there a simple solution for this?
Jan 28, 2014 at 3:00 PM
Well the way this works right now is that you have to set the DesignResolutionSize to the non retina size of the device and in the code you have to 'think' in non-retina dimensions.

For iPad this is easy because there are no different screen dimensions. So you can always set the

DesignResolutionSize = 1024 x 768

For IPhone its a little more difficult because you have 2 different aspect ratios.

My little hack I have above doesn't work for IPad because the content scale factor will always be set to 2.

Something along the lines of this should work for you:
var height = CCDrawManager.FrameSize.Height;
var contentScaleFactor = 1.0f;
// hard coded physical heights of hd devices
if (height == 2048 || height == 960 || height == 1136)
    contentScaleFactor = 2.0f;

CCDrawManager.SetDesignResolutionSize(CCDrawManager.FrameSize.Width / contentScaleFactor, height / contentScaleFactor, CCResolutionPolicy.ShowAll);
CCDirector.SharedDirector.ContentScaleFactor = contentScaleFactor;
Put this in your ApplicationDidFinishLaunching ...