Developing for iPad Retina Display in CoronaIn case you missed it, Corona SDK now officially supports “the new iPad” (or “iPad 3″, as I’ll be referring to it for the rest of this post) in both the public release and cutting-edge Daily Builds.

Since the iPad 3 sports four-times the number of pixels as the original iPad, there’s some confusion among some users as to how exactly graphical assets should be set up to ensure apps look their absolute best.

The good news answer is: generally the same way, that is, if you’ve been supporting Apple’s existing retina display for the iPhone and iPod touch. But just for the sake of alleviating any potential confusion, I’ll go over everything in this tutorial.

This blog post will be split up into a few different “scenarios”, which have to do with specific configurations and the types of devices your app will be targeting. You simply read over the section that best matches the scenario your app fits into best and follow the directions to get things working.

iPad-only Apps

This scenario applies if you are building your app specifically to target the iPad form factor alone (so that includes other tablets).

This is the easiest scenario to target, because it’s exactly identical to the way you’d create iPhone apps for the original iPhone and the newer iPhones with retina displays.

You create graphical assets as usual, and then make sure to have duplicate graphics that are exactly double the width and height of the original images. The double-sized graphics have a suffix appended to the file name (which you specify in your config.lua file), and the Corona engine chooses the correct graphics for you with dynamic content scaling.

Remember, you can’t just take any image program and blow up images to double the size. That would produce blurry images that would look identical to the original-size assets being scaled up, and would defeat the purpose of developing for the retina display. Instead, you’ll want to ensure your graphics are created at the highest resolution possible, and then exported for the original size, and then a version that’s double the original’s width and height.

Moving on, here’s an example listing of image files (we’ll use “@2x” for the image suffix):

  • star.png128 x 128
  • star@2x.png256 x 256
  • background.png768 x 1024
  • background@2x.png1536 x 2048

And here’s what the config.lua might look like to support the above images:


application =
{
content =
{
width = 768,
height = 1024,
scale = "letterbox",

imageSuffix =
{
["@2x"] = 2, -- images with "@2x" appended will be used for iPad 3
}
}
}

NOTE: Remember, despite which orientation you are targeting, you’ll always specify width/height in config.lua as if the device was in portrait orientation (with the width being the smaller of the dimensions).

In the sample config.lua above, the imageSuffix table has a single item, “@2x”, which will allow the Corona engine to know that on any device that is at least twice the size of the specified width and height, use images with “@2x” appended to them (if available).

Since we specified iPad dimensions for the width and height, double the width and height would be exactly equal to iPad 3 dimensions. Therefore, assuming you’re using the above config.lua, whenever an image is requested, the iPad 3 will be served “@2x” versions of the image (if available; if not it uses the exact image requested) for the iPad 3, while still serving the original-size graphic on the original iPad and iPad 2.

When you load the image using any of the Corona API’s, you’d just do it normally as if the “@2x” versions didn’t even exist! Corona is smart enough to serve the correct image, granted you set up config.lua correctly.


local bg = display.newImageRect( "background.png", 768, 1024 )

Using the above line of code in conjunction with the sample config.lua I provided, “background.png” would be served to the original iPad and iPad 2, while “background@2x.png” will be served to the iPad 3 and other supported devices with a similar resolution.

iPad + iPhone (Universal) Apps

This scenario covers apps that have screen dimensions matching that of the iPhone in config.lua (320×480), and take advantage of Corona’s dynamic content-scaling abilities to auto-scale the content to iPad dimensions. This type of setup ultimately results in an—albeit sharp—blown up version of your iPhone app.

Here’s an example of what your config.lua might look like in this scenario:


application =
{
content =
{
width = 320,
height = 480,
scale = "letterbox",

imageSuffix =
{
["@2x"] = 2, -- for iPhone, iPod touch, iPad1, and iPad2
["@4x"] = 4, -- for iPad 3
}
}
}

With the above config.lua, your app’s content width and height will be iPhone dimensions, no matter what device the app is running on. However, depending on the scale factor, either the “@2x” or “@4x” images will be served to devices with retina displays.

You may be wondering how I came up with the scale factors of 2 and the 4.

The numbers 2 and 4 above, which represents the scale factor for devices that will be served images with “@2x” or “@4x” appended to the file names simply means:

If the device’s screen is twice, or four times the specified width and height (320 x 480), search for images with the “@2x” and “@4x” suffix whenever an image is requested.

Getting the Scale Factor

And here’s a simple trick for determine the scale factor (hint: you can take advantage of Corona’s various simulator skins for this one!). Open the Corona Simulator (with the Terminal) and put the following into main.lua:


local deviceWidth = ( display.contentWidth - (display.screenOriginX * 2) ) / display.contentScaleX
local scaleFactor = math.floor( deviceWidth / display.contentWidth )
print( scaleFactor )

What the above code does is take the device width and divide it by the content width (and round that value down). This gives us the approximate scale factor for the device, relative to your config.lua’s width/height settings. We can use either the width and height to get this value, so I chose the width for the example.

If you switch to different device skins in the Corona Simulator, you’ll see the number changing. So to get the “@2x” scale setting, use the iPhone4 simulator skin (you should see a number 2 in the Terminal), and do the same for the “iPad Retina” (you should get the number 4 in the Terminal). You’ll also notice that the original iPad has a scale factor of 2 as well.

Cross-Platform Apps

This scenario applies if you’re planning on building a single binary and screen configuration that uses dynamic content scaling to support several devices with different form factors, including the iPad 3 of course.

The good news is, you’ll follow the exact same steps as you did in the previous scenario, but you’ll have more image suffixes defined in your config.lua’s imageSuffix table, and obviously have several different-sized versions of your images.

Here’s an example config.lua that supports a wide range of form factors using dynamic content scaling:


application =
{
content =
{
width = 320,
height = 480,
scale = "zoomStretch",

imageSuffix =
{
["@1-5"] = 1.5, -- for Droid, Nexus One, etc.
["@2x"] = 2, -- for iPhone, iPod touch, iPad1, and iPad2
["@3x"] = 3, -- for various mid-size Android tablets
["@4x"] = 4, -- for iPad 3
}
}
}

And that’s all there is to it!

You now have everything you need to develop cross-platform apps that are compatible with a wide range of screen sizes and form factors, including devices like Apple’s “resolutionary” new iPad.

  1. Jonathan,

    In your tutorial above, you instruct us to use displai.newImage() and not display.newImageRect() – has display.newImage been modified to support dynamic content scaling? If so, that would be great! But if not, you might want to update this post to avoid confusion for Corona newbies. Thanks as always! -Jason

  2. Thanks for the tutorial.

    What would be the best way to include iPad-filling background graphics on Universal apps though? As they will require not only different scale, but also a different proportion (or else they would be too thin). Currently I defined an array of images which are meant to fill the whole screen and then branch accordingly in the code, but perhaps there’s a more “native” way to do this.

    On a sidenote, hope you guys can help us Windows user with a Windows Retina simulator build :)

  3. Today, wouldn’t it make mores sense to just set the screen width to 640 and height to 960, and then provide @2x graphics for the iPad? The portion of devices that have a resolution of 320×480 is now so low that it doesn’t make much sense (especially because corona only supports iOs 4.3 or higher). However, I’m not sure if there is a noticeable performance decrease by doing that, I’ll have to test.

  4. Thanks for the tutorial! How can we add an app icon for iPad Retina btw? Is it as simple as adding a 144×144 image? I don’t have an actual device to test it with so I had to ask, sorry.

  5. Jonathan Beebe says:

    @Jason: Nice catch! The post has been updated to use display.newImageRect() — thanks for that :-)

    @Erick: For iPad and iPad 2, the icons are: Icon-72.png and Icon-72@2x.png respectively (Icon-72@2x.png is 144×144 pixels in size).

  6. And just to make this a complete resource, how about the sizes and file names for the various splash pages (Default.png) ?

  7. The article seems to assume the 1024×768 is the base screen, and the iPad 3rd Gen is a scaled up version. What if you want to target 2048 x 1536 and scale down to 1/4 for the folks with original and 2nd gen iPads? Or what if you want to restrict your app to *only* iPad 3rd Gen screens?

  8. @Philipp Lenssen Design your app by pretending that the screen is 720×960 (or 360×480 if your baseline is iPhone instead of iPhone Retina) with a 640×960 ‘safe area’. When it comes to full-screen assets, putting them in the center tends to work fine. For full-width objects that aren’t full height, some creative use of the xReference property keeps things in line.

  9. n00b here, be kind: so i thought the ipad 2 had twice the resolution of the ipad 1, and the ipad 3 has the most resolution of all. but according to this article, the ipad 1 and ipad 2 will use the originally sized graphics, and the ipad 3 will just grab the 2x graphics. i had the understanding that ipad 2 would need the 2x images, and ipad 3 would need something gargantuan.
    so we only need the original sized image file and one that’s at twice the size for the ipads 1, 2 and 3?
    thanks for all the helpfulness around the corona community :)

    (next up, optimizing all these images, my app is getting huge with all these graphics!)

  10. Hi guys. This seems to make sense, but now I’m wondering about how this ties in with positioning of all these graphics so that they’re arranged properly on each device.

    For example, at the moment I’m making an app that will become a universal iOS app, but at the moment the code specifies positions for all the interface elements in absolute values, based on the iPhone retina display.

    Is there a “best practice” method of defining static object positions based on the resolution of the device the app is running on?

  11. Guys,

    Quick question.. I am a bit confused abt the resolutions..

    Jonathan suggested the following, for Iphone/Ipad
    application =
    {
    content =
    {
    width = 320,
    height = 480,
    scale = “letterbox”,

    imageSuffix =
    {
    [“@2x”] = 2, — for iPhone, iPod touch, iPad1, and iPad2
    [“@4x”] = 4, — for iPad 3
    }
    }
    }

    but the resolution for Ipad1 and Ipad2 is 768 x 1024, by doing the 2x above isn’t the resolution just going to be 640 x 960?

    sorry might be a noob question

  12. As I understand it, those dimensions are for universal builds where you want your app up-scalable across all iDevices; @2x/4x isn’t gonna look perfect on iPad1/2/3 but it’s obviously better than using the base 320×480. If you’re creating an iPad-only app, just change the dimensions to 768×1024 and use @2x for iPad3. Hope that clears it up. Good luck guys~

  13. This solution also works for fullscreen “native.newVideos”?

    If not, how could I make an application with the native.newVideos work both on older ipads and the new one?

    Thanks!

  14. I’ve pretty much answered my own question above about a best practice for positioning and scaling interface objects for a universal iOS app. What I have done, and it works, is this:
    Set the “base” screen size as 320×480 (pre-Retina iPhone and iPod Touch), and then created three sets of interface graphics for everything. Those for iPhone 4 and iPad 1+2 displays are twice the size of the base size (with the “@2x” filename suffix) and those for the iPad 3 are four times the base size (with the “@4x” filename suffix).

    Using the code quoted by Vik above in the config.lua file, these are automatically used when the universal app is launched on higher resolution devices.

    Also, the main code of my app still specifies all object positions in absolute values (rather than factors of the display height and width), and they are automatically rearranged on the larger-screened devices, anchored around a centre point on the screen. This works well for my single-view app which is quite simple.

    To accommodate the iPad’s wider screen I’ve used background images at iPad aspect ratios.

    This just leaves the issue of the splash screen (default.png). Is there a way to specify different splash screens for different devices? Like, specifically a different splash screen each for iPhone 4, iPad 1+2, and iPad 3? Otherwise they become scaled and squashed to fit the screen and the effect is ruined.

  15. Is there an updated version of the button class used in the examples that uses newImageRect instead of newImage?

  16. I used the Daily build to fix my Ipad app for Retina display and have had no complaints but when I build with the current stable release it doest have a a simulator option for Ipad Retina and if used to build for xcode simulator it scales off screen. Is it accurate that Corona supports Ipad Retina in the public release. I just submitted a new iphone only app using the stable build and now want to do the ipad version. When possible I like to use the stable version so I have no surprises

  17. Rick – I’m having the same problem you are – but the daily build did not fix it. I am about to lose my mind over this. Does it work or not?! I have tried countless combinations if graphics dimensions, dpi , configurations , hardware and software and in all cases, the graphics show scaled double the target size on the iPad3.

  18. Hi Guys,

    iPad3. Is there a problem with this?

    I get something similar to Rick and Chris where the display shows what appears to be the lower right quarter of the app. The app displays OK on iPhone and iPod Touch and if you build for iPhone only then on the iPad3 you get the “standard” 1x vs 2x functionality.

    BUT – a universal build just does not want to work. This includes the sample code apps I’ve tested. My scale factor is 4 on the iPad3

  19. Hi Dave,

    I’m having the same issue as you. Trying to output an app using the public release to an iPad 3 for testing. Seems to be zooming into the lower right corner of the app for some reason.

    Any word if there’s a solution?

    Thanks!
    Paul

    • I’ve tried everything and I can’t get my images to scale.
      The relevant part of my config.lua is below.
      I have 4 images, named 2ship.png, 2ship@2.png, 2ship@3.png,2ship@4.png.
      The resolutions are 480×320, 960×640, 1024×768, 2048×1536 respectively.
      My display code in my storyboard is simple and copied below.

      Nothing scales when I test my application. I had my artists draw all my images for the iPad3 at 2048×1536 and I want to scale down for lower resolutions to support the lower res devices. Is there a better way to do this? I can’t get this code displayed here to work at all, I always get the 2ship.png image displayed, no matter what device I test it with. Any help would be Very Appreciated!

      ————-display code in screen 1 of my storyboard——————
      image = display.newImageRect( “2ndship.png”, 320, 480)
      image.x = display.contentWidth * 0.5
      image.y = display.contentHeight * 0.5
      screenGroup:insert( image )
      image.touch = onSceneTouch

      ——————————————————————
      —————————-config.lua below———————–
      application = {
      content = {
      width = 320,
      height = 480,
      scale = “zoomStretch”,
      fps = 30,
      imageSuffix =
      {
      [“@2″] = 2,
      [“@3″] = 3,
      [“@4″] = 4,
      },

      },

      • Please ignore my last post, duh…. I had the wrong image suffix on my computer…..
        I’m now getting the image I think I should be getting on the iPad3 but it doesn’t look great and I need to figure out why. At least Corona is now picking the right images at runtime for the iPad3, now that I fixed my typo…. I’m getting the wrong image on my iPad 2 so I need to play with my scaling factor. Also, the images are squished and look to be reversed so i need to work on this now.

  20. To all of you willing to work backwards (from full screen size, instead of 320×480), my suggestion is to set your largest images (for example, the background in 2048×1536 in the new iPad) as the “@1x”- for example: background.jpg. The @2 image, in my example for the old iPad, and the @4 for the iPhone.

    I just implemented it into Kwik and it is working fine (much easier than having to re-write everything from the scratch).
    Alex

  21. For Kindle Fire, I had to use the following line in my config.lua to make it work:
    [“@1_875x”] = 1.874999,
    1.875 did not work, I assume because of some floating point issue.
    Kindle Fire 1 is 600×1024 (320×1.875 = 600)

    • I’m just a noob here as well. On Kindle fire it is 600×1024 but it goes down to 600×1004 due to the bar at the bottom of the screen. I’m trying to find out if it is better to design two apps 1 for iphones/ipad and then 1 for the new iPad Retina. Just curious because right now I’m making it universal and I have about about 16 images and I am making 4 versions of each;

      image.png
      image@1.5x.png
      image@2x.png
      image@4x.png

      In the config file I have width = 320 height = 480. Everything seems fine however my file is getting larger and larger. Don’t want to discourage users from downloading that why I was thinking of making 2 versions of same app.

      Any input on this?

  22. It didn’t load the @2x image by using following code.
    Do anyone know what’s with that?
    Thank you
    ————————-config.lua————————————————————
    application =
    {
    content =
    {
    width = 320,
    height = 480,
    scale = “zoomStretch”,

    imageSuffix =
    {
    [“@1-5″] = 1.5, — for Droid, Nexus One, etc.
    [“@2x”] = 2, — for iPhone, iPod touch, iPad1, and iPad2
    [“@3x”] = 3, — for various mid-size Android tablets
    [“@4x”] = 4, — for iPad 3
    }
    }
    }
    ——————————————————————————————————
    image file: “bg.png” , “bg@2x.png” at “images/field”
    ——————————————————————————————————
    Here’s my display code :

    p0_moveGroup = display.newGroup()
    p0 = p0_moveGroup
    local touchSensor = display.newImage(p0_moveGroup,”images/field/bg.png”,true)
    touchSensor.isHitTestable = true
    touchSensor.x = display.contentWidth/2
    touchSensor.y = display.contentHeight/2

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>