HowTo: Backgrounds with no black borders on Apple/Android devices

One of the issues with cross-platform development on mobile devices is how to handle the diversity of screen-sizes in a visually pleasing way.
Corona handles this elegantly with its dynamic sizing, but how to get rid of those pesky black borders? Nobody likes those right?

After reading Matthew Pringle’s post http://j.mp/rBeLFq I was inspired to write a small app that demos a way to handle this issue.

You can get the source here: http://j.mp/vcqMoZ

The way it works is by creating an oversized image with a bleed-zone that will cover all devices.
The base image including bleed-zones should be 610x420, and for high-res (retina) you would create an 1220x840 image. (See the sample images from the source above to get a better understanding)

[lua]-- config.lua

application =
{
content =
{
width = 320,
height = 480,
scale = “letterbox”,

imageSuffix =
{
["@2x"] = 1.6
}
},
}[/lua]

The config.lua will inform Corona about the base-size of your canvas, and how to handle the scaling between devices. You only specify the size of your base screen without the bleed-zones.

The main.lua is very simple:
[lua]-- main.lua

display.setStatusBar(display.HiddenStatusBar);

– get the usable coordinates for the device
local screen =
{
left = display.screenOriginX,
top = display.screenOriginY,
right = display.contentWidth - display.screenOriginX,
bottom = display.contentHeight - display.screenOriginY
};

– get the background image
– please note that the reference-point is in the center of the image,
– by putting the image in the center of the screen the bleed-zones will only be
– displayed on devices with different aspect ratios than the base device.
local bg = display.newImageRect(“blob.png”, 610, 420);
bg.x = display.contentWidth / 2;
bg.y = display.contentHeight / 2;
– show usable coordinates
display.newText("left: "…tostring(screen.left), 10, 10, native.systemFont, 14);
display.newText("top: "…tostring(screen.top), 10, 25, native.systemFont, 14);
display.newText("right: "…tostring(screen.right), 10, 40, native.systemFont, 14);
display.newText("bottom: "…tostring(screen.bottom), 10, 55, native.systemFont, 14);[/lua]
This code will display your background image on any device without any annoying black borders.
Try it in the simulator and change the device type to see the beauty of it all… oh yeah :slight_smile:

You can also use the screen table to make use of the bleed area and know where it’s safe to put your objects and still be visible on the screen.

[import]uid: 70847 topic_id: 17798 reply_id: 317798[/import]

Thank you Ingemar.

Nice effort and beautiful sharing.
Regards,
Rodrigo. [import]uid: 89165 topic_id: 17798 reply_id: 67917[/import]

Nice, ingemar. When I’m ready to work on Android version, I’ll definitely refer back to this. Thank you for sharing!

Naomi [import]uid: 67217 topic_id: 17798 reply_id: 67977[/import]

ingemar,
Thanks for this sample project.

I must admit that I am a little confused, however, as to why you chose 1.6 as the value for the imageSuffix.

In playing around with it in the simulator, I did see that changing it to 2 (which is what I expected it to be) caused the Galaxy Tab to not display the high resolution image.

I think some of my confusion might be partly because the values displayed for the usable coordinates would not appear to be correct. For example, for the iPad, it comes back with:
left: -0
top: -20
right: 480
bottom: 340

Whereas I expected it to be:
left: 0
top: 0
right: 1024
bottom: 768

Or maybe I am just confused with how scaling really works and need to look into it some more. I am new to Corona. [import]uid: 17827 topic_id: 17798 reply_id: 78019[/import]

I chose 1.6 for the reason that you’ve already discovered.
It’s to make sure that other devices with a high-res display will still show the high-res version. You can experiment with this setting yourself, but this particular setting is where I’m happy with the results.

The coordinates you see displayed by the sample code are correct, and is a result of the letterbox scaling. When you specify a content size of 320x480 in config.lua, then your app will always be using these coordinates as a base when you place objects on the screen, regardless of the device its running on.
As you can see for the iPad, you get an extra 20 pixels on the top and bottom (0 to -20 and 320 to 340) to place objects on and still be visible on screen.

This makes it very easy to handle the placing of objects since you don’t have to worry about checking the device’s actual screen size. You just place your objects within the useable coordinates and let Corona do the math.
[import]uid: 70847 topic_id: 17798 reply_id: 78025[/import]

@ingemar

Thank you so much! I left this issue for last and now I needed it. Good timing. I tried and I can tell you that it is working like a charm with all devices (iphone, ipad, droid…)

Perfect!

Mo

ps: A big thanks to Matthew Pringle for his blog post as well. [import]uid: 49236 topic_id: 17798 reply_id: 78225[/import]

This is great info, thank you so much for sharing :slight_smile:

Larry [import]uid: 11860 topic_id: 17798 reply_id: 78323[/import]

great tut, thanks for sharing
its good for backgrounds, but what about other images on screen, what sizes should images be, if say its original size is 50x50px [import]uid: 16142 topic_id: 17798 reply_id: 78331[/import]

I’m not sure what you mean, but other images follow the same principle as the background.
A 50x50px image will be 50x50px in the context of the content size specified in your config.lua (in the example above the context would be 320x480).
When viewed on other devices images will be scaled accordingly to fit the letterbox scaling.

If you want to display higher res images on higher res devices, you use the dynamic scaling feature provided by Corona.

As an example you could create two images for your object, img50.png (50x50px for low-res) and img50@2x.png (100x100px for high-res). You would then use object=newImageRect("img50.png",50,50) to get the object and Corona will automatically choose the image that best suits the device it’s running on (using the directives you specify with the imageSuffix entry in config.lua). [import]uid: 70847 topic_id: 17798 reply_id: 78338[/import]

I’m still a little confused about this 1.6x vs 2x thing though I may be drawing a conclusion that if right is really cool.
This is my assumption based on what appears to be happening in your app (I’ve not tried it yet, just reading the forum thread…)

display.newImageRect() gets the device size and if its less than 1.6x the size in config.lua then it grabs the native image. If the device size is greater than 1.6x, i.e. 2x for a retina iPhone, then it will grab whatever is suffxed with @2x.

Instead of the assumption that 1.6x is how much bigger images are that are listed with that suffix. I’ve been making my retina graphics 2X the native ones like I should, but I’ve been using a scale of 2.0 in my config lua thinking that told Corona how much to scale my graphics up by.

If the former is the case, this is a major epiphany. [import]uid: 19626 topic_id: 17798 reply_id: 78343[/import]

You may now do your epiphany dance :slight_smile: [import]uid: 70847 topic_id: 17798 reply_id: 78351[/import]

wow, thats nice to know, you made my day [import]uid: 16142 topic_id: 17798 reply_id: 78354[/import]

I use 1.5 to show 2x graphics on the samsung galaxy s II (Resolution is 480 x 800). I can’t remember if I tried 1.6 with this device but 1.5 works perfect.

Raúl Beltrán
MIU Games [import]uid: 44101 topic_id: 17798 reply_id: 98562[/import]