Multi resolution help

Firstly a handy hint that all you Mac developers probably already knew - but I didn’t and it’s proving invaluable.

instead of running and debugging on an IOS device or (perish the thought) an emulator, i’m now developing for the Mac.

This means I can specify a window size of any dimension, and make sure all is well with the scaling etc.

Which leads me to my question:

I’m using the multi-resolution as described (for 2.2 unfortunately, but essentially the same) at http://www.cocos2d-x.org/wiki/Multi_resolution_support

I finally got it working so my background image(s) look fine at any resolution, using ResolutionPolicy::NO_BORDER

Now I have a problem positioning my sprites.

For example, I have a sprite that is acting as a button, and in my original code (designed at 1024 x 768) I positioned it at (20, 100)

When I run at 1024 x 768, all is well.

and all is well if I run at any resolution with the same aspect ratio.

But if I try a resolution that isn’t the same aspect ratio - so some of the background is cut off - then my lovely button is cut off too :frowning:

I kinda know what to do (calculate how much of the screen is cut off, and adjust my X by that amount would do it) but what I really think I want to do is position things relative to the screen, rather than by pixel.

Like using device independent positioning.

Now I seem to recall reading something about that for cocos2d-x - but can’t find anything now! Does it exist? If not can anyone recommend a good and efficient way of ensuring my stuff appears in the same relative space on teh screen at any resolution?

I doubt why didn’t you try positioning your sprite using getVisibleSize.width/2 and getVisibleSize.height/2 kind of things?
How is it that this didn’t work for you if your tried?

Hmmm…
When I set the window size to 1024 x 768, getVisibleSize returns 1024 x 768
When I set the window size to 1280 x 1024, getVisibleSize returns 960 x 768

I don’t understand what is going on there.

In any case - the visibleSize / 2 is fine for positioning in the centre - but I want to position close to the edge – and with the scaling going on, the first visible pixel on the screen is not necessarily at x == 0…

i had tried using 1/102 of the visible width (meaning 10 pixels at 1024 x 768) which should mean 12.5 pixels at 1280 x 1024, teh button is still offscreen, because the left of the screen is chopped.

Of course it is slightly worse with the ‘wrong’ value being returned by getVisibleSize()!

Your design resolution is 1024 x 768, which is a ratio if 1.33.
Your window size of 1024 x 768 is a 1:1 mapping to your design resolution.
A window size of 1280 x 1024 has a ratio of 1.25. This ratio is applied to your design resolution height of 768: 768 * 1.25 = 960.
This happens, cause your policy is NO_BORDER. It will stretch your assets with the new ratio.

To have the same relative space, you have to apply the new ratio to the offsets.

It’s not the wrong value. You told the engine to use NO_BORDER and this is the correct outcome.

Ok - thanks. It is sort of starting to make sense…
Actually, no it’s not!!

Did you mean ‘height’? because the width is returned as 960, the height stays at 768.

And if I multiply my 10px default offset for my button by 1.25 that gives me just 12.5 - which is a little closer but nowhere neat the correct position.

Just to be sure, I changed the screen size to be 640 x 512 (ensuring it is using the same assets in my case)

Director::getInstance()->getVisibleSize() returns 960 x 768 still

Which is consistent with this ratio - but still isn’t clear to me where the 960 and 768 come from, or what units they are in / what they refer to?

My Thoughts:
I am running this on a screen 640 x 512 pixels.
Design size is 1024 x 768

To fit the width in, it would have to multiply by 0.625. (640 / 1024 ) This would leave the height at 0.625 x 768 = 480 - but that is smaller than the screen height so would leave a border.

To fit the height in it would have to multiply by 0.666. (512 / 768) This would leave the width at 0.666 x 1024 = 682 - which is larger than the screen width - so graphics might be truncated by 682 - 640 = 42 pixels overall - or 21 pixels at each side.

Logic tells me then that I should position my sprite at 10 + 21 for it to be in the same location.
But then the 10 pixels are 10 pixels at 1024 x 768 which would need to b multiplied by the 0.666 to scale correctly

So 10 * 0.66 + 21 = 27.6

I tried that - and the button is hard left against the screen.

If I use a figure of 42 pixels, by button looks like it is in the right place - but that doesn’t make sense to me either!

Help! I’m lost in mathematical conflict!!

I’m getting the feeling that I will find a Wiki page about this with a marginal note saying “I have discovered a truly marvellous proof of this, which this margin is too narrow to contain.” :smile:

No, I meant height. The width is calculated by applying(multiplying) the ratio to(with) your height.

Your thoughts are correct, beside the truncation.
Your assets after scaling by the 0.666 factor is about 682x512. But the policy now truncates the width by the design width difference: 682 - 640 = 42. The new assets are now 640x512, which is a ratio of 1.25. The OpenGL coordinates have to be mapped onto that resolution by multiplying the design height by the screen ratio: 768 * 1.25 = 960.
And here you have your 960x768 again.

The units are in pixels and they refer to the mapping from design resolution to device resolution.

The difference between the frame width and the design width is still 1024 - 960 = 64, which is 32 pixels at each side!
So if your asset is 10 pixels to the right in your design width, it would be 10 + 32 in your screen width.

Your problem is, that you think the OpenGL coordinates are based on the scaled asset. They are not. They are always mapped to your design resolution. This made you forgot to scale the truncation with the scaling factor.

You scaled the wrong values. Not 10 has to be scaled, but the 21. Also you have to use the ratio of 768/512, as your design resolution is larger than your screen resolution:
768/512 = 1.5; 21*1.5 = 31.5; Non truncated values would be 21.33 * 1.5 = 32. Does this value sound familiar? Yes it does! It is the same as the 32 I calculated above, but with OpenGL coordinates, instead of asset dimensions.

To get to the final offset:
10 + 21*1.5 = 41.5. Non truncated values would be 10 + 21.33 * 1.5 = 41.995(in fact it would be exactly 42, cause the 22.33 is also just a rounded/truncated value).
Does that 42 sound familiar again? Yep:

Never scale the OpenGL coordinates, like you did with the 10! This is the offset based on your design resolution.

But with a hint: Scale the correct values :smile: