How to deal with Retina displays?

rene_ruppertrene_ruppert DEXamarin Team, University, XamUProfessors Xamurai

I did some testing in the iPad 2 Simulator and my scene looks nice. Then I tried the same on a Retina iPad and everything is tiny because CocosSharp uses real pixels. So I looked into the samples and found two ways out:

  • use the @2x suffix for my images
  • create an "hd" folder and add that to the content search path

What's the best approach if I want my tiles in my game to be 140x140 whatever-units (pixels on non Retina iPad)? And what about other platforms (Android) - when are they considered "hd"?

Answers

  • RamiTabbaraRamiTabbara AUMember, Xamarin Team Xamurai

    Hi René,

    I've opened up a proposed enhancement here which we'll hopefully try to incorporate into the next release.

    I think once implemented, this enachancement will encourage the general setup in the game app delegate of:

    • setting a fixed design resolution size irrespective of the true screen size
    • based on screen size, users will:
      • add "hd" or otherwise to the content search path as you suggested
      • specify the CCApplication.DefaultTexelToContentSizeRatio to scale the hi-res images accordingly
  • rene_ruppertrene_ruppert DEXamarin Team, University, XamUProfessors Xamurai

    Thanks @rtab - sounds like a good enhancement. What's my workaround for now? I have set design resolution to 1024x768 with policy "ShowAll".
    With that I make my game work on iPad 2 and I can use it on iPad Air with Retina too, it's virtually going to be 1024x768 on any device.
    Now the sprites: as you say the sprite resolution is what it is. I'm thinking to maybe have high-res versions of my sprites only and then manually scale them for now and use them for all platforms/resolutions. Does that make sense?

  • RamiTabbaraRamiTabbara AUMember, Xamarin Team Xamurai

    Hi René,

    Perhaps you could do something like:

    
    public override void ApplicationDidFinishLaunching(CCApplication application, CCWindow mainWindow)
    {
       // Other setup ...
    
       mainWindow.SetDesignResolutionSize(1024, 768, CCSceneResolutionPolicy.ShowAll);  
       
       // If using a retina iPad, the size will be 2048x1536
       CCSize winSize = mainWindow.WindowSizeInPixels;
      
       // Warning: assuming it's a landscape only application
       if(winSize.Width > 1024)
       {
            application.ContentSearchPaths.Add("images/hd");            
       }
       else
       {
            application.ContentSearchPaths.Add("images/ld");
       }
    
        // Setup starting scene...
    }
    
    
  • rene_ruppertrene_ruppert DEXamarin Team, University, XamUProfessors Xamurai

    But what if the device (some Android device maybe) has a screen width of e.g. 1500? It would pick the HD textures, but they will be too big, because they are meant for 2048 pixels width and that will break the UI unless I scale the sprites back down. Or do I misunderstand something here?

  • RamiTabbaraRamiTabbara AUMember, Xamarin Team Xamurai

    Hi René,

    I think you're understanding this, but to make sure there's no ambiguity and hopefully to help other users I'll explain this in a bit more detail.

    So first off, let's consider two screens with pixel dimensions as in the image.

    image

    You can think of these as normal and retina iPad respectively. Even though physically they're similar in dimensions, essentially the retina version is treated as if it's a screen of double the pixel size.

    Now, suppose in my game app delegate I set the design resolution of my window

    
    mainWindow.SetDesignResolutionSize(1024, 768, CCSceneResolutionPolicy.ShowAll);
    
    

    This sets the default bounds of any layers as seen below:

    image

    Notice that my dimensions are in points (pts) not in pixels. This is in terms of the world space of the game -- that is the coordinate system where all our game objects live. By default a layer created will have it's camera fixed so that the bottom-left hand corner is at the origin (0,0) and the top-right corner is at (designWidth, designHeight).

    The key point here is that both screens have the same worldspace.

    Now, when I go to add a sprite to my layer, by default we set the texel dimensions as the world space ContentSize of our node as below

    image

    This is because it would be a pain for a user to manually set the ContentSize for each and every sprite they want to include within their game.

    If we instead have a larger hd version of our image, then currently nothing special happens - it just appears bigger on our layer because it is!

    image

    So this is where the enhancement will become useful, because rather than simply using the texture pixel dimensions to determine the content size, we want to incorporate some additional scaling factor. In other words, we want the ContentSize measured in points to be consistent across different quality images.

    Finally, let's suppose we have a weird sized screen or worse we set the game to be in portrait. If we're using the CCSceneResolutionPolicy.ShowAll policy then the viewport will be setup so that it maintains the same aspect ratio as the specified design resolution as seen below.

    image

    But again, there's no concern about doing some additional scaling in this case. As you can see in the above figure the world space will be scaled accordingly. (i.e. The maximum design height no longer take up the entire screen).

    So in general you don't need to worry about weird-shaped screens. The only concern you should have is this: relative to my design resolution (i.e. worldspace), are the pixel dimensions of my sprites correct so that when the corresponding ContentSize is set they fit in my game world correctly?

Sign In or Register to comment.