Affiliate links on Android Authority may earn us a commission.Learn more.
Writing your first Android game using the Corona SDK
August 22, 2025
The most popular category on the Google Play Store has always been Games. Although we all probably use key productivity apps like a web browser, an email client, and an instant messaging app, gaming still remains an important part of the mobile experience. So it is no surprise that many people who want to learn to develop for Android want to start by making a game. Also, let’s be honest, writing a game is a whole load more fun than developing a productivity app!
The official language of Android is Java and the official development environment is Android Studio. If you want to look into Java then I suggest ourJava basics tutorial, and if you want to learn how to write an app using Android Studio then I suggest you check out ourtutorial on writing your first Android app. However Java and Android studio aren’t the only ways to develop for Android. You can find an overview of the available languages and SDKs in our guide:I want to develop Android Apps – What languages should I learn?

One of the SDKs mentioned in the programming languages guide is Corona, a third party SDK designed primarily for writing games. Instead of Java, Corona uses Lua, a fast scripting language that is easy to learn yet powerful. However, Corona isn’t the only mobile gaming SDK that uses Lua, other well known examples includeCocos2d-X,Marmalade, andGideros.
Download and install
To get started with Corona you are going to need to download and install the SDK. Go to theCorona websiteand hit the download button. You will need to create an account (which is free) before you may download the kit. If you want to build an actual .apk file rather than just running your program in the emulator, you will need to install Java 7, however you won’t need to install the Android SDK. To install the Java 7 Development Kit go toOracle’s website, look for the section called “Java SE Development Kit 7u79″ and download the version for your PC.
Once you have installed Corona you need to activate it. This is a one-time process, which is free. Start the Corona Simulator and agree to the license. Enter in the email address and password which you used for the download, and click Login.

Starting the project
From within the Corona Simulator click on “New Project.” Enter a name for your app in the “Application Name:” field and leave the rest of the settings at their defaults. Click “OK.”
Three windows will now appear. The first two are the Corona Simulator and the Corona Simular Output. Corona will also open a file explorer window showing the files for your project.

The majority of the files (some 23 of them) in the project directory are for the application icon! The most important file for us right now ismain.lua, as this is where we will write the code for our app.
Introduction to Lua
Before we get into writing the code, we need to make a whistle-stop tour of Lua. The Lua interpreter (remember this is a scripting language, not a compiled language) is available for Windows, OS X, and Linux. However it is built-in to Corona, so at this time you don’t need to install anything extra. The easiest way to play with Lua is to use theonline live demo.
you’re able to find lots of good tutorials about Lua online and you should take a look at theLua Reference Manual,Programming in Lua,The.Lua.Tutorial, andThe Tutorials Point Lua Tutorial.

Here is a small Lua program which will show you some of the key features of Lua:
The code above shows three important Lua constructs: functions, loops, and if statements. The functiondoubleIt()is very simple, it just doubles the passed in parameterx.

The main code is aforloop from 1 to 10. It callsdoubleIt()for each iteration. If the return value is 10 (i.e. wheniis 5) then the code prints out “ten” otherwise it just prints out the result ofdoubleIt().
If you have any coding experience then the example code should be easy enough to follow. If you are looking to learn some basic programming then I suggest you use some of the resources linked above to hone you skills.
Writing the game
Writing basic programs in Corona is simple. You only need concern yourself with one file,main.lua,and let Corona do all the heavy lifting. The game we are going to write is a simple “tap” game. A balloon or a bomb will fail down the screen. If the player taps on the balloon they score a point, they tap on a bomb then the score will divided by 2, as a penalty. To write the code you need to editmain.lua. You can do this in any text editor.
The Corona SDK has a built-in 2D physics engine, which makes building games very easy. The first step in writing the game is to initialize the physics engine:
The code is fairly self-explanatory. The module physics is loaded and initialized, it is assigned to the variablephysics. To enable the enginephysics.start()is called.
Next we create some helpful variables which will be useful not only for this simple game, but also for more complex games.halfWandhalfHhold the values for half of the screen width and half of the screen height:
Thedisplayobject is a pre-defined object which Corona makes globally available.
Now comes the first step that actually makes something happen on screen:
As well as properties likecontentHeightandcontentWidth, thedisplayobject also has lots of useful functions. ThenewImage()function reads an image file (in this case a .png) and displays it on the screen. Display objects are rendered in layers, so since this is the first image we are putting on the screen then it will always be the background (unless the code explicitly does something to change that). The parametershalfWandhalfHtell Corona to place the image in the middle.
At this point you’re able to run the code in the emulator and see the background image. If you save the file then the emulator will notice that the file has changed and offer to relaunch. If that doesn’t happen then use File->Relaunch.
Since the user will score points for tapping on balloons, we need to initialize a score variable and display the score on the screen:
The score will be kept in the imaginatively named variablescore,andscoreTextis the object which displays the score. LikenewImage(),newText()put something on the screen, in this case text. SincescoreTextis a global variable then we can change the text at any point. But we will get to that soon.
You can relaunch the emulator and see the score of 0 display towards the top of the screen.
Now comes something a bit more tricky, but don’t worry I will explain it line by line:
The code above defines a function calledballoonTouched()which will be called every time a balloon is tapped. We haven’t yet told Corona to call this function every time the balloon is tapped, that will come later, but when we do this is the function that gets called.
Tap or touch events have several stages, many to support dragging. The user puts their finger on an object, this is the “began” phase. If they slide their finger in any direction, that is the “moved” phase. When the user lifts their finger from the screen, that is the “ended” phase.
The first line ofballoonTouched()checks we are in the “began” phase. We want to remove the balloon and increment the score as soon as posible. If the function is called again for other phases like “ended” then the function does nothing.
Inside theifstatement are four lines of code. Let’s deal with the last two first, as they are simpler.score = score + 1just increments the score by one andscoreText.text = scorechanges the score text on the screen to reflect the new score. Remember how I said thatscoreTextwas global and could be accessed anywhere, well that is what we do here.
Now for the first two lines. Once a balloon or bomb falls of the bottom of the screen it still exists in the app’s memory, it is just that you can’t see it. As the game progresses the number of these off-screen objects will steadily increase. Therefore we need to have a mechanism which deletes objects once they are out of sight. We do that in a function calledoffscreen, which we haven’t written yet. That function will be called once per frame during the game. Once a balloon has been tapped then we need to delete it and remove the call that checks if the balloon has gone offscreen.
The lineevent.target:removeSelf()deletes the balloon. When a touch event occurs one of the parameters of the listener function is theeventparameter. It tells the function about the event and what type of event it is, e.g.event.phase.It also tells us which balloon was tapped,event.target.TheremoveSelf()function does what it says it does, it deletes the object (in this case a balloon).
The line before that removes the “enterframe” listener, which is the function that is called every frame to see if the balloon has fallen off the bottom of the screen. We will look at that in more detail when we come to write theoffscreenlistener function.
So, to recap.balloonTouched()checks that this is the beginning of the touch sequence. It then removes the “enterframe” listener, which is the function that is called every frame to see if the balloon has fallen off the bottom of the screen. It then deletes the balloon, increments the score and displays the new score.
That was for balloons, now we need something similar for bombs:
As you can see the code is very similar with the exception that rather than incrementing the score, the score is multiplied by 0.5 (i.e. divided by 2). Themath.floor()function rounds down the score to the nearest integer. So if the player had a score of 3 and tapped a bomb then the new score would be 1, and not 1.5.
I mentioned theoffscreen()function earlier. This function will be called every frame to check if an object has gone off screen. Here is the code:
In computing there is a situation known as a race condition. This is where two things are going to happen but one might happen first, or sometimes the other might happen first. It is a race. Some race conditions are unseen because one thing always seems to happen first, but they can cause interesting bugs in that one day, under the right conditions, the other thing happens first and then the system breaks!
There is a race condition in this simple game because two things can happen very close to each other: a balloon being tapped and theoffscreen()function being called to see if the balloon has gone off the screen. The result is that the code to delete the balloon can be called and then theoffscreen()function is called (which happens like 30 times per second). To get around this odd sequence of events theoffscreen()function needs to check if theyvalue of the object isnil(null) or not. If it isnilthen it means that the object has been deleted already, so move along, these aren’t the droids we are looking for.
If the object is still in play, then check its position, if it has gone 50 pixels off the screen then delete it and remove the listener so that theoffscreen()function won’t be called again for this object. The code to make sure thatoffscreen()is called every frame is part of the next section of code.
The whole premise of this game is that new balloons or bombs will continue to drop down the screen. Therefore we need a function which will create either a new balloon or a new bomb:
The first line of the function decides where the balloon will drop from on thexplane. If the balloon or bomb always dropped in the middle, that won’t be very interesting! SostartXis a random number between 10 percent and 90 percent of the screen width.
Next a random number is picked between 1 and 5. If the number is 1 then a bomb will be dropped. If it 2, 3, 4 or 5 then a balloon will be dropped. This means that bombs will be dropped around 20 percent of the time.
The bomb and balloon code are quite similar. First the image (either a bomb or a balloon) is displayed usingnewImage().Itsxposition is that ofstartXwhile itsyposition is set to -300, i.e. off the top of the screen. The reason for that is that we want the object to fall from outside the screen area into the visible area and then off the bottom. Since we are using the 2D physics engine it is good to give the object a bit of an initial distance to fall, so it can gain some speed.
The call tophysics.addBody()takes the image loaded bynewImage()and turns it into an object in the physics engine. This is very powerful. Any image file can be made into a body which responds to gravity and collisions just by callingphysics.addBody().
The last three lines of the bomb or balloon code set up the listeners. Setting theenterFrameproperty tells Corona which function to call every frame and the call toRuntime:addEventListener()sets it up. Lastly the call toballoon:addEventListener()tells Corona which function to call if the bomb or balloon is touched.
And now the game is almost complete. We just need two more lines of code:
The first line makes the very first bomb or balloon fall by explicitly callingaddNewBalloonOrBomb(). The second line sets up a timer which will calladdNewBalloonOrBomb()every half a second (500 milliseconds). This means that a new balloon or bomb will fall every half a second.
You can now run the game in the emulator.
Here is the complete listing for main.lua, the full project source code for this game can be foundhere on GitHub.
Next steps
The next step is to play the game on a real Android device. To build an .apk file click on File->Build for Android… and fill out the fields. The result will be a .apk file which you may copy onto your device and then install. You will need to ensure that you have configured your device to allow installation of app from unknown sources.Amazon has some good documentation on thisas you also need to set this to install the Amazon Appstore. Corona also has a guide onhow to sign, build, and test your app on Android devices.
With the game successfully installed on your device the next thing to do is improve the game. For example, why not try adding a “pop” or “bang” sound everything a balloon or bomb is tapped. Corona has an API for that:media.playEventSound().
Or why not trying adding a third type of object, say a super boost which doubles the current score, or how about some background music?
Writing games with Corona is quite straight forward because the SDK handles things like OpenGL and it includes a built-in 2D physics engine. Also Lua is easy to learn and shouldn’t be hard for anyone with even the minimum of programming experience. The Coronalabs website has lots ofdocumentationincluding lots ofguidesandtutorials.
In less than 100 lines of code we have a working game. OK, it isn’t going to win any prizes, however it shows the power and flexibility of the Corona SDK.
Thank you for being part of our community. Read ourComment Policybefore posting.