CAUTION: This tutorial is outdated and the material cannot be confirmed as accurate. A new guide covering this topic is coming soon.

This article is designed to get Flash developers quickly oriented within Corona. First, I’ll discuss how to take your existing Flash projects and turn them into Corona projects, followed by a more general introduction to Corona from a Flash perspective.

(1) Exporting Assets from Flash

A good first step is to export all your graphical assets. When porting from Flash Lite on older devices, I generally recreated higher-resolution assets for the larger iPhone and Android screens. However, web-based Flash games will likely have assets that are already a good size for today’s mobile devices. And of course, if the assets are vector-based, you can resize them within Flash before exporting them as bitmaps.

When exporting assets, it’s usually easiest to open a second, empty FLA and use that as a “scratchpad”: copy and paste each element from your source FLA into the empty FLA, then export, then delete the asset from your scratchpad.

For non-animated graphics, you can use the built-in image exporter in Flash (select File > Export > Export Image).

For an export format, I generally choose PNG, because it’s high-quality and also supports transparency. In addition to PNG, Corona will also import JPEG images, and this may make your compiled application size somewhat smaller — but note that it won’t save any runtime memory, since all images are loaded into uncompressed 32-bit graphics memory on the device.

In Flash’s PNG export dialog, there are two settings to be aware of. The “Include” menu should generally be set to “Minimum Image Area”, which should snap to the boundaries of the assets that are currently onstage.

You can also choose “Full Document Size”, which will use the boundaries of the stage itself, but you’ll probably only want to do that when exporting your background graphics.

For “Colors”, choose either “24 bit” or “24 bit with alpha channel” (if your image includes transparency). 8-bit PNG files are not supported on iOS.

Using a similar process, animated movieclips can be exported from Flash as a numbered series of bitmaps, suitable for use in either the “movieclip” library (see below) or for merging into sprite sheets. Choose File > Export > Export Movie to export the current timeline as an image series.

You’ll be presented with the same image export dialog as above, but in this case the filename you choose will be used as a base name for a series of numbered files — if your filename is “disk”, the resulting files will be named disk0001.png, disk0002.png, and so on.

In cases where you have an animated character with differently-sized states that you want to make consistent, or you simply want to create extra margin around your graphics, one handy technique is to add an invisible layer beneath your assets, sized to the image dimensions that you want to export. In the example below, a 200 x 200 rectangle has been added to the stage, with its alpha value set to zero. Even though this object has no visible pixels, its size will be automatically taken into account during the Flash “Minimum Image Area” export process.

You may need to consider layout changes due to the different aspect ratio of mobile devices — in landscape, most devices are more “widescreen” then the average Flash game on the web, which are often closer to a 4:3 aspect ratio. However, in many cases, you can minimize this by extending or creating additional background graphics on both sides, while leaving most of the layout unchanged.

The important thing is to keep in mind the range of devices and platforms you are ultimately interested in. Currently, Android devices are somewhat taller and skinnier (or, in landscape, more “widescreen”) than iPhone/iPod devices. Meanwhile, the iPad is closer to being square, with a 3:4 (or 4:3 in landscape) aspect ratio.

Corona’s content scaling lets more easily target a variety of iOS and Android devices, because it will automatically resize your content for each screen. However, depending on the scaling mode you choose, you may need to add optional “filler” background graphics that will only be visible on some devices, to avoid black bars around the edges of your screen — or, in other cases, you may want to allow for content being cropped at the edges on some devices. This topic deserves its own article, and happily, we have one: see this discussion of content scaling and multi-screen deployment with Corona.

What if you only have a SWF file?

In cases where you’ve misplaced your legacy FLA source (haven’t we all done this at least once?) and only have a SWF movie file, your best bet is to run the SWF through a decompiler to recreate the FLA. I’ve personally gotten a lot of good results over the years from the Sothink SWF Decompiler. It’s not free software, but it pretty much pays for itself the first time you recover a lost-source client project!

The machine-generated code you’ll get from a Flash decompiler may not always be friendly or readable; for example, the original variable names will be replaced by short, generic gibberish. But the important thing is that you’ll regain access to the assets in the library, and can then extract them individually.

(2) Importing Assets into Corona

The “Movieclip” library

The movieclip.lua library, found in the “Graphics/Movieclip” sample code, was designed as a convenient way to handle Flash-style animation. As input, it takes a list of sequential image files:

[cc lang=”lua”]myAnim = movieclip.newAnim{ “cube1.png”, “cube2.png”, “cube3.png”,
“cube4.png”, “cube5.png”, “cube6.png” }[/cc]

The result is an animated graphics object that responds to a variety of commands, including: play, reverse, stop, nextFrame, previousFrame, stopAtFrame, playAtFrame, setDrag and setLabels.

The documentation for the movieclip library can be found here, and for a quick demonstration, see the “Graphics/Movieclip” sample project distributed with Corona.

Sprite sheets

While the Movieclip library is good for basic animation, for complex character animation you will generally want to use the Sprite API, which significantly reduces your graphics memory used (often by half or more). Rather than working with a sequence of separate image files, this class uses “sprite sheets”, which are large graphics containing many individual animation frames.

Why is this important? The major difference between desktop Flash and mobile development is that memory management suddenly becomes critical, rather than merely polite. Because Corona’s graphics are fully hardware-accelerated, the most important resource on the device is its graphics memory, which is the area of memory that can be directly accessed by the GPU. No matter how much runtime memory the user has available, graphics memory remains limited by the buffer size of the GPU hardware — this limit is roughly 20MB on the iPhone 4 and iPad, and 10MB on older iPhones and most other devices.

Also, this buffer is used up much faster than you’d expect. Bitmaps are created in memory at 32 bits per pixel, meaning that a single 512 x 512 image consumes a full megabyte. Even worse, this memory must be allocated in powers-of-two dimensions, meaning that a 300 x 300 image consumes the same memory as a 512 x 512 image. This wasted space around each image obviously adds up if you have a lot of separate images, and so it’s preferable to combine the animation frames into the largest image size supported by the device hardware (which is 2048 x 2048 on iPhone 4 and iPad, and 1024 x 1024 on most other devices).

To create a sprite sheet, you begin with a series of images, just as you would for the “movieclip” library above. But rather than importing them as separate files, you first merge them using a sprite sheet tool, which also creates the data for reading back the individual frames into your program (see tutorial here). Two utilities that support the creation of sprite sheets for Corona are Zwoptex and TexturePacker, both available via the Corona Tools page.

For examples of sprite sheets in action, see the “Sprites/HorseAnimation” and “Sprites/JungleScene” sample projects; the former has been recently modified to serve as an example of “packed” sprite sheets, while the latter uses the simpler grid-style sprite sheets.

Since you’ll need the same series of source files whether you choose the movieclip library or the Sprite API, you can easily get started using the movieclip method, and then migrate to sprite sheets later — it’s up to you.

Audio Files

The OpenAL-based audio API in Corona will read most common audio formats on iOS (and shortly Android), so you may not need to convert your audio files at all. For a discussion of the performance tradeoffs between different audio formats, see this article.

(3) Lua for Flash Developers

The Lua language, and the Corona application frameworks, should be quite intuitive to anyone who uses Actionscript (or any other scripting language). I’ve previously converted Actionscript game logic by simply pasting the Actionscript source into my Corona projects and then quickly converting it line by line, since the translation is usually quite straightforward.

Here are some quick tips to get you started:

Words, not brackets

One difference from Actionscript that you’ll notice immediately is that Lua uses keywords, rather than brackets, to mark out code blocks:

[cc lang=”actionscript”]
// Actionscript version:

for ( i-1; i< =100; i++ ) { trace(i); if ( i > 99 ) {

[cc lang=”lua”]
— Lua version:

for i = 1, 100 do
if ( i > 99 ) then

You’ll quickly get used to using keywords like “do”, “then” and “elseif”, and then Lua will become much easier to read.

This difference results from Lua reserving the bracket characters for declaring tables. A “table” in Lua is an array of values or name/value pairs — not only is it the fundamental data structure in Lua, it’s literally the only type of object that exists in Lua:

[cc lang=”lua”]
myTable = { “a”, “b”, 100, “hello” }

otherTable = { x=5, y=7, name=”Joe” }

newTable = {}

newTable[1] = “a”

newTable.x = 5

newTable[“name”] = “Joe”


Lua is a language with very few datatypes: string, number, function, table, boolean and nil. The variables are loosely typed, and can be cast whenever you like:

[cc lang=”lua”]
myValue = 4
myString = tostring(myValue)

myValue = “12”
myNumber = tonumber(myValue)

You can also test datatypes as follows:

[cc lang=”lua”]
myValue = 10
local myType = type(myValue)
if ( “string” == myType ) then
print( “This value is a string” )
elseif ( “number” == myType) ) then
print( “This value is a number” )
elseif ( “function” == myType ) then
print( “This value is a function” )

A powerful feature of Lua is that functions are considered “first-class variables”, and they behave just like any other datatype. For example, functions can be returned as values from other functions, assigned to variables, or stored in tables.

This can be used to do some interesting things: for example, the “Movieclip” library, discussed above, creates a lightweight object by adding various animation playback functions to a Lua table, along with a sequence of images.

(For a more advanced discussion, see this section from Programming in Lua on “closures” in Lua.)

Variable scope

Lua variables are either global or local, and all variables are global unless specifically declared as “local” (which limits their scope to their current code block).

In Lua, it is a best practice to use local variables wherever possible, both for code organization and because the runtime overhead is somewhat lower. For example, the second case below will execute about 30% faster than the code above it, simply because the global “math.sin()” function has been copied to a local variable, resulting in faster memory lookup.

[cc lang=”lua”]
— Version 1:
for i = 1, 1000000 do
local x = math.sin(i)

– Version 2:
local sin = math.sin
for i = 1, 1000000 do
local x = sin(i)

For this reason, you’ll see the “local” keyword prefacing nearly all variables and functions in Lua examples. Again, you’ll quickly get used to this.

(4) Corona for Flash Developers

Corona has extended the core Lua language with hundreds of APIs and frameworks, many of which have been designed with Flash developers at least partly in mind. Here are some of the first things you’ll probably look for:


Corona includes a transition system, with sytnax that is probably self-evident if you come from the Flash world:

[cc lang=”lua”]
local myTween = objectName, { time=3000, x=200, alpha=0.5,
transition=easing.outExpo } )

Also, Stuart Carnie of Manomio has created an extended transition library, featuring many more easing types. This external library can be found in the Corona SDK Code Exchange, and is also included as the “easingx.lua” file used in the “Physics/MultiPuck” sample project to get the “bounce” effect when a new puck is spawned.


Since any graphics object in Corona can be a listener for touch events, it’s easy to make buttons from scratch. But it’s even easier if you use the newButton() function in the “ui.lua” library, included with many of the Corona sample projects, such as “Interface/ButtonEvents”.

Using this library, you can construct buttons with rollover graphics, event handlers, and optional “iOS-style” embossed text:

[cc lang=”lua”]
local myButton = ui.newButton{
default = “buttonRed.png”,
over = “buttonRedOver.png”,
onPress = myPressFunction,
onRelease = myReleaseFunction,
text = “Press Me”,
font = “Trebuchet-BoldItalic”,
textColor = { 255, 255, 255 },
size = 22,
emboss = true

Events and Listeners

Events in Corona are handled by assigning functions to named events; this will also feel intuitive to Flash developers:

[cc lang=”lua”]
local animationFunction( event )
redBall.x = redBall.x + 10
Runtime:addEventListener( “enterFrame”, animationFunction )

local locationHandlerFunction( event )
print( “Your current location: “, event.latitude, event.longitude )
Runtime:addEventListener( “location”, locationHandlerFunction )

local lowMemoryFunction( event )
print( “Low memory warning!” )
Runtime:addEventListener( “memoryWarning”, lowMemoryFunction )

Corona’s event listeners are used for a wide array of tasks: receiving sensor data (GPS, compass, accelerometer), handling touch or textfield input from users, detecting collisions in the physics engine, performing asynchronous HTTP/HTTPS calls and remote image loading, using reverse geocoding with Google Maps, and obtaining Facebook login responses.

Listeners can be set either globally (“Runtime listeners”) or locally within an object (“table listeners”). For an example of a runtime listener, see the “Hardware/GPS” sample code, and for examples of both types, see the “Physics/CollisionDetection” sample. In this latter example, table listeners are used as an optimization, because they limit the broadcast of collision data to include only the objects of interest.


iOS devices ship with several dozen fonts built in, and to use them in Corona, you simply need their full name, as defined within the OS (e.g., “Trebuchet-BoldItalic”). To see a complete list of fonts on your target device, use native.getFontNames().

In contrast, Android devices tend to ship with only a few built-in fonts (e.g., Droid Sans and Droid Serif). The good news is that on both platforms, you can include additional custom fonts with your Corona app; see documentation here. Custom fonts must be accessed using their font name, not their filename — you can always get the currently available font names by using native.getFontNames().

Note that because font files can be easily extracted from your mobile application bundles, any custom fonts you include with your app must be licensed for redistribution, not just for commercial use. Most fonts on your system probably aren’t licensed in this way, but there are a growing number of freely-redistributable fonts, such as those released under the Open Font License (OFL).

Setting Framerates

Corona runs at 30 fps by default, and optionally at 60 fps. The framerate is restricted to these values because Corona’s animation is locked to the physical screen refresh rate of the iPhone/iPad to increase animation smoothness. This means that framerates must be evenly divisible into 60.


This month’s upcoming Corona release includes a new bitmap masking feature, allowing you to turn an image file into an alpha mask (including soft-edged masks), and then apply it to another image. This process is quite straightforward:

[cc lang=”lua”]
local myImage = display.newImage( “image.png” )
local myMask = graphics.newMask( “circlemask.png” )
myImage:setMask( myMask )

Once created, a mask can be re-used on multiple display objects, and the scaling properties of each instance of the mask can be manipulated independently. See the “Graphics/Flashlight” and “Graphics/X-ray” sample projects for examples of bitmap masking.

Vector Graphics

While most of the examples in this article assume the use of bitmap graphics, Corona also includes vector drawing APIs for rendering outline or filled rectangles, rounded rectangles, and circles, in addition to arbitrary line segments. This can come in quite handy — for example, see this Bezier Curve demo, or the “line of force” drawn between your finger and the cueball in the “Physics/SimplePool” sample.

However, contrary to what you might expect, bitmap graphics typically result in higher performance than vector graphics on mobile devices, so while you may want to use vector graphics for specific purposes, you’ll generally find yourself using bitmaps most of the time.

Game Physics

For complex games, you will often want to rely on Corona’s physics engine for automatic interaction between game elements, rather than scripting all your motions with transitions. The Corona physics engine is built on the popular Box2D, which is also used in many physics-based Flash games on the web, making those games even easier to port directly to Corona.

A significant difference under the hood is that Corona embeds the native C++ Box2D library, and therefore runs at full native speeds on devices. In tests against the Flash CS5 Packager for iPhone last spring, I observed fairly dramatic speed differences in Corona versus Box2D-Actionscript: the “ManyCrates” test literally ground to a halt when running under Flash on iPhone. Interestingly, the bottleneck in this case seemed to be the intensive floating-point math, rather than the graphics output — I assume this is due to the automatic code translation of the Flash Packager not performing as well as Erin Catto’s hand-optimization of his C++ library.

Also, while the Actionscript API for Box2D is a direct copy of Box2D in C++, the Corona physics API is radically simpler and easier. So if you’re already familiar with Box2D, you’ll recognize all the features, but if you haven’t worked with a physics engine before, then you’ve come to the right place!

You may have already seen our award-winning “Physics in 5 Lines” demo, which shows how any graphics object can be instantly converted into a physics object. A good place to get started on your own is by running and experimenting with the various projects in the “Physics” sample code subdirectory on the SDK (or see here to download individual samples).

For some full game examples with source code, see Jonathan Beebe’s “Ghosts vs. Monsters” and “Martian Control”.

For a simpler case, see the “Physics/SimplePool” sample project in the Corona SDK, which shows how a two-player billiards game can be written in less than 200 lines of code. (As an aside, I created all the SimplePool graphics in Flash, which I tend to use as a “poor man’s Illustrator” when drawing game assets.)

Corona also includes what I believe may be the only current multitouch implementation of Box2D — to see this feature, build and run the “Physics/MultiPuck” sample project on the multitouch device of your choice.


If you’re using Facebook integration in your Flash project, you can go on using it in Corona, including the new Graph API and the Facebook Places service (which can be combined with Google Maps in Corona). See the “Networking/Facebook” sample project for an implementation example.

Touch, Drag and Multitouch

Any graphics object in Corona can be set to receive touch events; these events occur in different phases (“began”, “moved”, “ended” and “cancelled”). For simple examples of draggable objects in Corona, see the “Interface/DragMe” and “Interface/DragMeMultitouch” sample projects.

Dragging active physics objects is slightly different, since the physics engine will generally expect to remain in control of the objects’ positions, and you may get odd behavior if you try to “fight” the engine with manual intervention. For this reason, you will usually get better results by dragging from within the simulation. This is done by creating a temporary “touch joint” in the physics world between your finger(s) and the target object. To make this simple, the “gameUI.lua” library features a “dragBody()” function that makes any object multitouch-draggable in a few lines:

[cc lang=”lua”]
local function dragBody( event )
gameUI.dragBody( event )

myObject:addEventListener( “touch”, dragBody )

For an implementation example, see the “Physics/MultiPuck” sample project.

As an interesting footnote, “MultiPuck” doubles as a visual test of the multitouch capabilities of different device screens. If you build the project for iPhone, you’ll see that it will track five simultaneous touches, and the iPad will actually track eleven touches. Meanwhile, Android devices usually seem to support a maximum of two simultaneous touches (except for Android 1.5/1.6 devices, which don’t support multitouch at all).

More subtly, we’ve discovered through our testing that some Android screens, including the Nexus One, are apparently built to detect two-finger “pinch/zoom” gestures, but will fail to properly track those two touches if they cross each other’s x- or y-axis. I’m guessing that this is due to early rounds of Android devices reportedly being repurposed from Windows Mobile 6.x hardware designs, and now that Android has come into its own as a platform, I would expect these hardware limitations to be resolved in future devices.

In any case, the first axiom of mobile development will remain true: always test on a range of the actual hardware you are targeting!

Further Reading

The Corona API reference can be found here, along with many useful articles in the “Docs” area.

Also, if you’re new to the Lua language, you’ll probably want to pick up a copy of Programming in Lua (online version here). Since Lua tends to be heavily used in game development, you’ll find a variety of other books and online forums about Lua in that context, especially relating to World of Warcraft, which famously exposes its Lua API to end users.

  1. Coming from serious AS3 game development, Corona is a “god send”. I have been able to port some very complicated game elements with ease given the tools provided in this article. My game runs as 1fps (one!) with the Flash to iOS packager but runs in full 30FPS using Corona. Thank you, thank you, thank you.

  2. What are ‘best practices’ for organizing code in corona? I AS3 it is easy to seperate all of your code into classes to keep everything neat and organized. How would one accomplish this with LUA?

  3. I also wonder like Ben how you keep your project clean organizing class files like you would with as files.. If someone can clarify this, it would be great. So far I have one folder with one very long main.lua file, lots of png around, and it starts to be a bit messy..

  4. Hi Ben & Seb,

    I am starting an application and I am also quite interested in how can I keep my organize with Corona SDK.

    Did you find an answer for that ?

  5. For the directory structure, note that Corona is fine with all graphics and sound assets in sub-folders, it’s just the code files that have to be in the root folder. That works out pretty nicely, because I organize my projects with code in the main folder, graphics in the “graphics” folder, and audio in the “audio” folder.

    As for organizing the code into classes in separate files, take a look at the approach I use:

    I know a lot of other people use metatables for doing OOP in Lua, so you might want to look that up in the forum too.

  6. correction to my comment: Putting files in folders works on iOS but I don’t think that works on Android. I don’t know for sure because I’m not developing for Android.

  7. All in all you need to jump from OOP Horse to script donkey redoing everything. I personally don’t see any converting. Redoing yes. What is actually converted. I’m understanding by converting doing something automatically not manually. Cos manually is just having good guide and do line by line as state with “copy action script code and then code in lue” :))
    Ofcourse you can reuse image but exporting every asset from flash and especially movie clips keyframe interpolation and actionscript control is far from exporting every frame in bmp and package with Texture packager. Don’t take take in consideration class structure interfaces design patterns and else. So If you converting pong game yes you can recoded.

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>