Project Configuration

Configuration settings for an app are defined using a config.lua file written in Lua syntax. It should be placed in the project's base directory.

Basic Structure

The config.lua file is set up using a content table nested within a application table as follows:

application =
{
    content =
    {
        -- Parameters
    }
}

Content Scaling

Since most apps are developed for multiple devices and screen resolutions, Corona features several content scaling options. This allows you to use a common set of screen coordinates while Corona automatically scales text, vector objects, and images to different resolutions depending on the device.

Corona can scale both upward or downward depending on your starting resolution. It can also substitute image files of differing resolution when needed, ensuring that your app appears clear and sharp on all devices (see Dynamic Image Selection below).

Content Area

A fundamental concept behind content scaling is content area. In Corona, your base content area can be whatever you wish, but often it's based around a common screen width/height aspect ratio like 2:3, for example 320×480.

The content area represents the overall "stage" on which text, vector objects, and image assets are displayed. Everything will be positioned in relation to this content area, which may or may not match the screen's actual pixel resolution. The content area will be scaled to fit the screen, with subtle differences dictated by the scale definition (see scale below).

The internal coordinate system is also dependent on the content area, with coordinates (0,0) residing in the top-left corner of the content area, not necessarily the top-left corner of the screen. For more information on the Corona coordinate system, see the Group Programming Guide.

width | height

The content area is defined by the width and height values in config.lua. If you omit or set either of these values to 0, content scaling will not be used.

application =
{
    content =
    {
        width = 320,
        height = 480,
    }
}
Important

The content area should always be defined in respect to portrait orientation. If your app is designed for landscape orientation, you should still set the width and height according to portrait orientation. In the example above, a landscape-oriented app should still use width and height parameters of 320 and 480 respectively, not 480 and 320.

To control an app's orientation on actual devices, you must define specific parameters in the build.settings file. See Project Build Settings for more information.

scale

The scaling method of the content area is determined by the scale value. If you omit this (not recommended), the width and height values will be ignored and the content area will be set to the device's actual pixel width and height.

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

The possible scale values include the following:

  • "letterbox" — scales the content area to fill the screen while preserving the same aspect ratio. The entire content area will reside on the screen, but this might result in "black bars" on devices with aspect ratios that differ from your content aspect ratio. Note, however, that you can still utilize this "blank" area and fill it with visual elements by positioning them or extending them outside the content area bounds. Essentially, "letterbox" is an ideal scale mode if you want to ensure that everything in your content area appears within the screen bounds on all devices.

  • "zoomEven" — scales the content area to fill the screen while preserving the same aspect ratio. Some content may "bleed" off the screen edges on devices with aspect ratios that differ from your content aspect ratio. Basically, "zoomEven" is a good option to ensure that the entire screen is filled by the content area on all devices (and content clipping near the outer edges is acceptable).

letterbox zoomEven
  • "adaptive" — instead of a static content area, a dynamic content width and height is chosen based on the device. This uses platform-dependent heuristics so that the virtual DPI (number of Corona content units per inch) is approximately 160 across devices. On iOS, the width and height is chosen to match the native iOS point width/height of the device (most iOS devices maintain roughly 160 points per inch). On Android, a combination of the standardized DPI (mdpi, hdpi, etc.) and the actual screen width/height in pixels is used to calculate a virtual width/height, assuming a virtual DPI of 160. In the Corona Simulator, this scale matches content width and height to simulate the device. Note that "adaptive" mode is not supported for macOS desktop apps, Win32 desktop apps, or Windows Phone apps.

  • "zoomStretch" — scales the content area to fill the entire screen on any device, ignoring the content aspect ratio. This mode should be used with caution since it will stretch/warp images and text if the device's aspect ratio doesn't exactly match the content area's aspect ratio.

xAlign | yAlign

By default, scaled content is centered on the screen. In letterbox scale mode, empty screen area will be evenly divided between both sides. In zoomEven mode, the bleed area will be cropped equally on both sides.

If you need to align the content area to a particular edge of the screen, you can use the xAlign and yAlign values.

  • xAlign — string value which sets the alignment in the x direction. Possible values are "left", "center", or "right".

  • yAlign — string value which sets the alignment in the y direction. Possible values are "top", "center", or "bottom".

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox",
        xAlign = "left",
        yAlign = "top"
    }
}

Dynamic Image Selection

In addition to content scaling, Corona supports dynamic image selection. If you are developing an app for both normal and Retina/HD devices, you should not rely on Corona to simply scale one set of images across a wide array of screen resolutions. There are several issues related to this:

  1. If you design all of your images in low resolution and allow Corona to scale them up for Retina/HD devices, the images will appear blurry or pixelated. Not only will this result in poor visual appearance, but it may cause the app to be rejected before it reaches the marketplace.

  2. In contrast, if you design all of your images for Retina/HD and allow Corona to scale them down for lower resolution devices, the larger images will require the same amount of texture memory on those devices. This may adversely affect the performance of your app — or worse, those images will not appear if they exceed the maximum texture size on a device.

The solution is to create multiple versions of every image, tailored for two or three different resolutions, and name them according to the "image set" they belong to. On each device, Corona will automatically select images from the set that most closely matches the content area and scale.

Important

This feature is only supported by images displayed using display.newImageRect() or by sprites and images taken from image sheets that contain the overall sheet size parameters.

To set up dynamic image selection, you must include an imageSuffix table within the content table. Inside this table, declare at least one key-value pair consisting of an image suffix and a scale factor.

imageSuffix =
{
    ["@2x"] = 2.0,
    ["@4x"] = 4.0
}

As indicated, each image suffix must be specified within brackets and quotes as in ["@2x"]. The suffix can be named whatever you want, but it should be short and logical since you must append the same suffix to all image files designed for that image set. When adding a suffix to each image file, do not include the bracket or quotes — just append the suffix itself, for example myImage@2x.png or myImage@4x.png.

The second part of each declaration is the scale factor. This value specifies the scale threshold above which Corona will use images in that suffix set. The following code can help you determine the proper values:

print( display.pixelWidth / display.actualContentWidth )

Add this code to your project, access the Corona Simulator, and use Window → View As to simulate different devices. Note the output in the Corona Simulator Console — this is the scale factor for the device. If the value on a particular device is greater than or equal to the number you specify for the scale factor, Corona will use images from that suffix set.

Important

If you use widgets from the Corona widget library, you must adhere to the standardized @2x and @4x suffix options, otherwise the proper hi-resolution assets will not be selected on Retina/HD devices. Note that this rule does not apply for visually-customized widgets for which you've created custom assets and/or image sheets — in this case you can use any suffix setup and name the assets accordingly.

Example

In the following example, just one suffix is defined ("@2x"), but it accommodates several high-resolution devices. Resolutions below this scale factor will simply use the non-suffixed image set. A non-suffixed image set should be included in every project as a basic precaution — this ensures that if a particular device falls outside of the scale factor range(s) you've defined, Corona can use these images instead.

application = 
{
    content = 
    { 
        width = 320,
        height = 480,
        scale = "letterbox",
        xAlign = "center",
        yAlign = "center",
        
        imageSuffix =
        {
            ["@2x"] = 1.5
        }
    }
}
Note

Although you can define as many image sets as you wish, there are simply too many screen sizes and aspect ratios to achieve a perfect 1:1 ratio on all of them. Thus, you must accept some degree of scaling, even when using dynamic image selection. In most cases, you should set up image suffixes that target devices of similar resolution, then allow Corona to scale the images up or down slightly depending on the device. This minor degree of scaling will generally not be perceived by the end user, since most modern devices have a very high pixel density. As noted at the top of this section, it's better to scale images down versus up and you should attempt to construct a scaling setup that achieves this on the most popular devices.

Content Properties

Several properties are exposed within Corona to help you work with scaled content, including those mentioned below. Please refer to the API Reference for a complete list.

Runtime Errors

In the Corona Simulator, there is a setting under Preferences called Show Runtime Errors which defaults to on. This global setting triggers pop-up error messages while running an app in the Simulator. If you don't like this feature or if it doesn't fit your workflow, you can turn it off.

You can also set this on a per-app basis from config.lua to control error messages while running the app on a device. showRuntimeErrors accepts a boolean value (true or false). The default depends on whether the app is built for distribution: if an app is built with a developer provisioning profile or the debug keystore then showRuntimeErrors will default to true, otherwise it will default to false. Obviously, an explicit setting will override the default.

application =
{
    showRuntimeErrors = true,
}
Notes
  • Remember that disabling error messages doesn't mean that errors aren't occurring. The pop-up alerts simply help you detect these errors.

  • Another option is to use the unhandledError Runtime listener to trap errors which would otherwise trigger an error pop-up. This allows you to implement custom error reporting. Note that even if you disable error messages, the listener is still called, but the return value doesn't matter since the pop-up is never displayed.

function myUnhandledErrorListener( event )

    local iHandledTheError = true

    if ( iHandledTheError ) then
        print( "Handling the unhandled error", event.errorMessage )
    else
        print( "Not handling the unhandled error", event.errorMessage )
    end
    
    return iHandledTheError
end

Runtime:addEventListener( "unhandledError", myUnhandledErrorListener )

Frame Rate (fps)

The default frame rate is 30 frames per second, but you can set it to 60 frames per second by adding the fps key. Values other than 30 or 60 will be ignored.

application =
{
    content =
    {
        fps = 60,
    }
}

App Licensing

The Corona licensing library lets you confirm that the app was bought from a store. To implement licensing, the license table must be added to the application table of config.lua:

application =
{
    license =
    {
        google =
        {
            key = "YOUR_LICENSE_KEY",
        },
    },
}

Please see the licensing documentation for full details on how to implement and execute licensing.

Shader Precision

This is used to override the default shader precision for all OpenGL ES shaders (on devices).

Acceptable values are "highp", "mediump", and "lowp".

You should not specify this unless you absolutely require higher precision and see no performance impact from setting it.

application =
{
    content =
    {
        shaderPrecision = "highp",
    },
}

Fine Tuning

Assigning a string value as outlined above will change the meaning of all precision qualifier macros. Thus, another option is to set individual precision macros by assigning a table to shaderPrecision. This table should contain Corona precision qualifier macros as keys and OpenGL ES precision qualifiers as values, for example:

application =
{
    content =
    {
        shaderPrecision =
        { 
            P_POSITION = "highp",
            P_UV = "mediump",
            P_COLOR = "lowp",
        },
    },
}

Acceptable keys are P_DEFAULT, P_RANDOM, P_NORMAL, P_POSITION, P_UV, and P_COLOR.

Acceptable values for these keys are "highp", "mediump", and "lowp".

For more information, see the Precision Qualifier Macros section of the Custom Shader Effects guide.

Note

Assigning a value/table to shaderPrecision will change the behavior and performance of all custom shader effects and built-in effects.