Allowing your application to integrate with social networks is a great way to promote your finished product. Many games enable the player to upload their high scores and share them among other users who are playing the same title. Some provide challenges that need to be completed successfully in order to unlock achievements. Social networks enhance the gaming experience and provide great exposure for the developer.
We'll also go into more detail about build configuration since we're getting more accustomed to programming. Understanding the importance of configuring your device build is vital for cross-platform development. This is a capability that Corona SDK can handle with ease across iOS and Android devices.
In this chapter, we will learn the following topics:
Let's add in these finishing touches!
Build settings and runtime configuration were briefly discussed in Chapter 2, Lua Crash Course and the Corona Framework. Let's get into more specific details on how to handle a variety of devices that work on the iOS and Android platforms.
There are a variety of ways to handle device orientation to match the settings your game design requires.
There are scenarios in which you want the native user interface (UI) elements to autorotate or to be oriented in a certain way, but you also need to maintain a fixed coordinate system within Corona.
To lock Corona's orientation while allowing the native iPhone UI elements to rotate, add a content parameter in build.settings
as follows:
settings = { orientation = { default = "portrait", content = "portrait", supported = { "landscapeLeft", "landscapeRight", "portrait", "portraitUpsideDown", }, }, }
To lock Corona's internal coordinate system to portrait orientation while locking iPhone UI elements to the landscape orientation, you could do the following in build.settings
:
settings = { orientation = { default ="landscapeRight", content = "portrait", supported = { "landscapeRight", "landscapeLeft", }, }, }
The Android platform supports portrait and landscape orientations. The orientation portraitUpsideDown may not be available on some Android devices. Also, autorotation is not currently supported on Android. The default orientation doesn't affect Android devices. The orientation is initialized to the actual orientation of the device (unless only one orientation is specified).
Here is an example of an Android-specific build.settings
file (you might also combine Android and iPhone settings in the same file):
settings = { android = { versionCode = "2", versionName = "2.0" usesPermissions = { "android.permission.INTERNET", }, }, orientation = { default = "portrait" }, }
The versionCode
and
versionName
fields can be set within an optional "android"
table in build.settings
.
The versionCode
field is defaulted to "1"
, while the versionName
field is defaulted at "1.0"
if it's not set in the build.settings
file. When an updated version of an application is submitted to the Google Play Store, the versionCode
and versionName
fields also have to be updated. All version numbers for versionCode
have to be whole numbers. The versionCode
field cannot contain any decimal numbers, while the versionName
field can contain decimals.
For more information, see android:versionCode and android:versionName at http://developer.android.com/guide/topics/manifest/manifest-element.html#vcode.
An optional "usesPermissions"
table can be used to specify permissions, using string values as given in the Android manifest reference: http://developer.android.com/reference/android/Manifest.permission.html.
Developers should use permissions that match their application requirements. For example, if network access is required, the Internet permission needs to be set.
For more useful information on the android.permission
keys applied in Corona SDK, refer to http://docs.coronalabs.com/guide/distribution/buildSettings/index.html#permissions.
Content scaling throughout multiple devices can be frustrating at times if you've never addressed them before in your config.lua
file. There are many individual screen sizes. The size of iPhone 5 is 640 x 1136 px, and that of iPad 2 is 768 x 1024 px. The size of Droid is 480 x 854 px, and that of the Samsung Galaxy tablet is 600 x 1024 px, just to name a few. Memory can run out easily due to image size boundaries.
When setting up your config.lua
, like we've done in the previous chapters, we had our content set to width = 320
, height = 480
, and scale = "letterbox"
. If building for Android devices, "zoomStretch"
works best to accommodate varying screen sizes on the platform. This creates a common build for iOS and Android and presents display images that are large enough to fit on a variety of screen sizes.
If you want to scale for larger screen sizes and then scale down, use the screen size of the iPad 2. Your config.lua
would look similar to the following code:
application = { content = { width = 768, height = 1024, scale = "letterbox" } }
While the preceding example is another solution to scale content, it's important to remember the limitations in texture memory involved with larger (high resolution) images. While devices such as the iPad with Retina display, iPhone 5s, and the Samsung Galaxy Tab 4 tablet will handle this just fine, the iPhone 4s and older devices will have far less texture memory available to handle large graphics.
A way to resolve this potential problem is to use dynamic image resolution to substitute assets that are better suited for low-end devices and high-end devices. We will discuss this topic in more detail later in this section.
As you may have noticed, some of the background images we used in our sample apps are scaled at 380 x 570. This happens to be the size that fills the entire screen on all common devices for both iOS and Android. Better yet, it is a middle ground to compensate for higher- and lower-resolution images on any device.
In order for your content to be displayed as evenly as possible, the following must be set up accordingly:
Settings for config.lua
are as follows:
application = { content = { width = 320, height = 480, scale = "letterbox" } }
In any file that contains any of your display images, a typical background would be displayed as follows:
local backgroundImage = display.newImage( "bg.png", true ) backgroundImage.x = display.contentCenterX backgroundImage.y = display.contentCenterY
Any content with a size of 320 x 480 is considered the focus area. Anything outside of the area is cropped, but will fill the screen with content on any device.
We know we can swap base images used for smaller devices (iPhone 4s) and larger devices (iPhone 6 and Kindle Fire HD). This occurs when trying to scale multiple devices in the same build.
A file-naming scheme is available for use to handle such devices for iOS and Android. Knowing how to handle the scaling of assets affected for the device proposed is half the battle. We'll have to define what resolution scale needs to be addressed for Corona to access the assets they're directed toward.
Using the line display.newImageRect( [parentGroup,] filename [, baseDirectory] w, h )
will call out your dynamic resolution images.
Typically, we've used ["@2x"] = 2
to call out the higher resolution image when available in our project for iOS devices:
application = { content = { width = 320, height = 480, scale = "letterbox", imageSuffix = { ["@2x"] = 2, }, }, }
The preceding example will only work for iPhone 4s and iPad 2 since it surpasses the base size of 320 x 480 on both devices. If we wanted to make it accessible to the Droid 2, the scale threshold would be 1.5. For an Android tablet to work, such as the Samsung Galaxy tablet, the scale threshold is 1.875. So how do we figure out these numbers? Simple. Take the width of the higher-end device and divide it by 320 (the base size). For example, the Droid 2 dimensions are 480 x 854. Divide 480 by 320 and it equals 1.5.
The Samsung Galaxy Tab 4 tablet's dimensions are 800 x 1280. Divide 800 by 320 and it equals 2.5.
If trying to manage both iOS and Android devices in the same project, you can change your imageSuffix
in config.lua
, as shown in the following code:
imageSuffix =
{
["@2x"] = 1.5, -- this will handle most Android devices such as the Droid 2, Nexus, Galaxy Tablet, etc...
}
Alternatively, you could use the following code:
imageSuffix =
{
["@2x"] = 2.5, -- this will handle the Galaxy Tab 4 and similar sized devices
}
Using either of the preceding examples will trigger the proposed Android devices to display the higher-resolution image.
The imageSuffix
string doesn't necessarily have to be "@2x"
; it can be anything like "@2"
, "_lrg"
, or even "-2x"
. As long as your higher-resolution image has the intended suffix after the primary image name, it'll work just fine.
High-resolution sprite sheets are not handled the same way as dynamic image selections. While you can continue using the same naming convention to differentiate your high-resolution images from your basic images, the image will not be able to use display.newImageRect()
when referring to sprite sheets.
If your current content scale is width = 320
, height = 480
, and scale = "letterbox"
in your config.lua
file, then the scale output for the following devices will demonstrate the following:
iPhone = 1
iPhone 4s = 0.5
Droid 2 = 0.666666668653488
iPad 2 = 0.46875
Applying a basic sprite sheet that matches the scale for an iPhone will display sharp and clean images. When the same sprite sheet is applied to the iPhone 4, the display will match the content scale of the device, but the sprite sheet will look slightly pixilated and blurry around the edges. Using display.contentScaleX
and calling some methods will solve that problem for you. Notice that displayScale < 1
will access the high-resolution sprite sheet based on the preceding device scale:
local sheetData local myObject local displayScale = display.contentScaleX –- scales sprite sheets down if displayScale < 1 then –- pertains to all high-res devices sheetData = { width=256, height=256, numFrames=4, sheetContentWidth=512, sheetContentHeight=512 } else sheetData = { width=128, height=128, numFrames=4, sheetContentWidth=256, sheetContentHeight=256 } end local sheet = graphics.newImageSheet( "charSprite.png", sheetData) local sequenceData = { { name="move", start=1, count=4, time=400 } } myObject = = display.newSprite( sheet, sequenceData ) if displayScale < 1 then --scale the high-res sprite sheet if you're on a high-res device. myObject.xScale = .5; myObject.yScale = .5 end myObject.x = display.contentWidth / 2 myObject.y = display.contentHeight / 2 myObject.x = 150; myObject.y = 195 myObject: setSequence("move") myObject:play()