Question about how to handle multiple screen sizes

Topics: Android
Mar 18, 2014 at 8:10 PM
Edited Mar 18, 2014 at 8:21 PM
I was wondering what the recommended way was to handle multiple screen sizes in Android. With iOS I only had to worry about 4 devices but with Android there seem to be a lot more. From what I have learned from my research, the below are a list of Android screen sizes that are most commonly used. I was thinking of first getting the screen size using CCDirector.SharedDirector.WinSize and from their see if it falls in the list of supported resolutions below. If its higher than whats listed, default at 1280x800, it is something in-between this list, use the lower of that range. Thoughts on this? Any more elegant ways to handle this?

1280x800
1280x768
1024x600
1024x800
1024x768
800x400
800x480
Coordinator
Mar 18, 2014 at 9:21 PM
Step 1. Choose a target resolution for your game
Step 2. In your AppDelegate class you setup the DesignResolution of the framework to match your #1 resolution.
Step 3. Assets are scaled accordingly by the framework, you get this for free
Step 4. Add @2 resolution assets to get higher resolution support, if so desired.

I've not found a solid reason to fully support the resolution of every target device. Your package would have to be so enormous in size that it would anger most users who don't want to spend the 250MB just to load your game.

If you find that the above steps produce an ugly game experience, then you chose a bad target resolution in #1.

For our latest game I chose 768 x 1024 as the design resolution. This has mapped well to desktop, android phone, wp8, mac os, and ios. That resolution does not map to a console experience though, which would not fit in the above steps. If you are targeting Ouya or Xbox or PS4 then you would need to set the resolution to exactly match your HD or SD console experience.

The critical factor in the resolution determination is aspect ratio. Choose one that best scales to the other resolutions with very little noticeable distortion.
Mar 18, 2014 at 9:30 PM
I noticed CCDrawManager.SetDesignResolutionSize method which works well. But what happens if my decided resolution is is larger than the device thats running my game? In your last game you used 768 x 1024, what if the device running your game is only 480 x 800 ?
Coordinator
Mar 18, 2014 at 9:36 PM
Edited Mar 18, 2014 at 9:37 PM
SetDesignResolution has 2 parameters, one is size, and one is a direction on what to do with the size mismatch.

I set it to FitExact which will fill the entire screen. You can experiment with the options to find one that suits your game. You can letterbox the game in some cases, but I have found that stretching the game to fit the screen works fine when the design resolution is chosen wisely.
May 29, 2014 at 4:26 AM
Thanks for the clarification. It makes sense now. However, I can't seem to get iPhone 5 (4in) to display properly.
Using:
       designSize = new CCSize (1024, 768);
      CCDrawManager.SetDesignResolutionSize(designSize.Width,designSize.Height, CCResolutionPolicy.ExactFit);
I get side letterboxes (black columns on left/right). All other device types and resolutions seem fine.
Any idea what I'm missing?
Coordinator
May 29, 2014 at 4:53 AM
In CCDrawManager, line 1171:
    public static void SetDesignResolutionSize(float width, float height, CCResolutionPolicy resolutionPolicy)
    {
        Debug.Assert(resolutionPolicy != CCResolutionPolicy.UnKnown, "should set resolutionPolicy");

        if (width == 0.0f || height == 0.0f)
        {
            return;
        }

        m_obDesignResolutionSize.Width = width;
        m_obDesignResolutionSize.Height = height;

        m_fScaleX = m_obScreenSize.Width / m_obDesignResolutionSize.Width;
        m_fScaleY = m_obScreenSize.Height / m_obDesignResolutionSize.Height;
Do you have the correct screen size for the device? If not, then MonoGame and Xamarin.iOS are not getting the expected viewport size.

On line 443 of the same file:
        m_obViewPortRect = new CCRect(0, 0, pp.BackBufferWidth, pp.BackBufferHeight);
        m_obScreenSize = m_obViewPortRect.Size;
Make sure you have the correct back buffer size. Your Game1 constructor may be setting the presentation parameters by mistake. Check that as well.
May 29, 2014 at 6:41 PM
Edited May 29, 2014 at 6:44 PM
Ok, I've checked the code you linked. Its getting called twice. The first time, both Heights and Widths are the same as the design size (1024x768). The 2nd time, it gets 960x640 - which is still not the correct 4in iPhone size (1136x640).

If I run the GameStarterKit project w/o any changes, I get this image:
https://www.dropbox.com/s/w087lbb2cbd7e8y/default_design_resolution.png

If I only change these lines in the AppDelegate:
    preferredWidth = 1024;
    preferredHeight = 768;
I get this image: https://www.dropbox.com/s/zhrnkmuv9bdzha9/1024_768_design_resolution.png

Also, here is the sample project I'm using - in case that would help: https://www.dropbox.com/s/dadtcj84v29fgc8/GameStarterKit.zip
Coordinator
May 29, 2014 at 6:53 PM
The 960 x 640 is coming out of MonoGame. Your runtime is reporting 176 pixels less than your actual screen size. I wonder why that is ...

The two images are different because of the scaling factor used to fit the contents into the window.
May 29, 2014 at 7:08 PM
Thanks for the response. Any suggestions on what I can do to move forward?
Seems odd that I would be the only one to have this issue.

I guess I'll try to delete everything and grab a fresh source tree. Maybe something got out of sync.
Coordinator
May 29, 2014 at 7:13 PM
I just checked our Santa Shooter game on Android and it scaled to fill the entire screen properly.

My thinking is that there is some setting in your iOS configuration (those plist files that are specific to iOS) that is telling your runtime to reserve space for a system menu. Make sure that you remove that setting.
May 31, 2014 at 12:52 AM
Edited May 31, 2014 at 12:54 AM
Turns out this wasn't a problem with iOS config or system menu space, etc. I did, however find a workaround.

To summarize the issue:
MonoGame does not seem to report the correct screen size for a 4in iPhone.

Workaround:
I removed the SetDesignResolutionSize call in the AppDelegate.cs.
I moved this call to the game layer, and it magically started reporting the proper size.
It will automatically pick up any @2x suffix'ed images, however it sizes it incorrectly for retina devices. Not sure if this is because I'm not calling the SetDesignResolutionSize call in the proper place. I have had to do the following:
CCDrawManager.SetDesignResolutionSize (568, 320, CCResolutionPolicy.ShowAll);
CCDirector.SharedDirector.ContentScaleFactor = 2;
Side note: I'm building a universal app, so for background images, I'd like to support four versions: normal phone, retina phone, normal ipad, retina ipad. So far, I am able to support all iOS devices with the following code. I designed the phone images to fit the 4in device, so I only need four version of images (for 3in retina & non-retina it will use the 4in images w/o distortion).
if (size.Height == 1136) {
            // 4in retina 640x1136
            CCDrawManager.SetDesignResolutionSize (320,568, CCResolutionPolicy.ShowAll);
            CCDirector.SharedDirector.ContentScaleFactor = 2;
        } else if (size.Height == 960) {
            // 3in retina 640x960
            CCDrawManager.SetDesignResolutionSize (320,480, CCResolutionPolicy.ShowAll);
            CCDirector.SharedDirector.ContentScaleFactor = 2;
        } else if (size.Height == 480) {
            // 3in non-retina 320x480
            CCDrawManager.SetDesignResolutionSize (320,480, CCResolutionPolicy.ShowAll);
            CCDirector.SharedDirector.ContentScaleFactor = 1;
        } else if (size.Height == 1024) {
            // iPad non-retina 768x1024
            CCContentManager.SharedContentManager.SearchPaths.Clear ();
            CCContentManager.SharedContentManager.SearchPaths.Add ("hd");
            CCDrawManager.SetDesignResolutionSize (768, 1024, CCResolutionPolicy.ShowAll);
            CCDirector.SharedDirector.ContentScaleFactor = 1;
        } else if (size.Height == 2048) {
            // iPad retina 1536x2048
            CCContentManager.SharedContentManager.SearchPaths.Clear ();
            CCContentManager.SharedContentManager.SearchPaths.Add ("hd");
            CCDrawManager.SetDesignResolutionSize (768, 1024, CCResolutionPolicy.ShowAll);
            CCDirector.SharedDirector.ContentScaleFactor = 2;
        }
This seems overly complex, but it seems to work. I'm not sure if it will break other drawing functions. Will keep going and see :)
Coordinator
Jun 3, 2014 at 12:14 AM
The design resolution determines how your screen elements are placed. If you change the design resolution then you will need to change the positioning of your screen elements.

The content scale factor is used to adjust the size/scale of high-def and non-high-def items in the game. The "hd" search path should already be added by the content manager.

When you play the game on these other resolution targets do you see the screen elements showing up at unexpected locations on the screen?
Jun 5, 2014 at 5:45 AM
Edited Jun 5, 2014 at 5:41 PM
Thanks...I'm finally starting to get this now. You are correct - I would have had to include the scale factor in all the positioning calls to make it work with my original code above.

I removed the scale factor and made the design resolutions pixel-accurate. Now I can target all iOS devices with one code base and less complexity than what I wrote before. Most of my placements are % of screen height/width, but I do have a few where I have to position differently based on dimensions.

I see that the platform is already looking for the "hd" directory, but I have the ipad images there and it wasn't finding them first if I didn't put those lines in. It would find them in the default /Content dir, which contains the iPhone sized images. With my hack above, I was able to keep them all the same image names.

Appreciate your assistance. I'm off to full coding mode now. Hopefully won't get stuck again! :)