Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
  1. Code
  2. Corona SDK

How to Build Highway Dodge With the Corona SDK

What You'll Be Creating


In this tutorial, you learn how to create, Highway Dodge, a simple, yet addictive, game. Highway Dodge is easy to pick up and play, but it provides the addictive quality of other popular games in the App Store.

Highway Dodge starts out by placing the player in a race car on the highway. During the game, the player must dodge oncoming traffic on the highway by tapping on one of the three available lanes. For every dodged car, the player receives one point and it’s game over for the player when an oncoming car hits the race car. Over time, the oncoming cars come out faster and faster in order to provide a real challenge to the player.


This game is built using Lua and the Corona SDK. At a minimum, you need to have an account with Corona Labs and the Corona SDK installed. You can grab the Corona SDK for free at the Corona Labs website. For this tutorial, I used build 2015.2731 of the Corona SDK.

1. Setting Up Highway Dodge

Let’s jump right in and start Highway Dodge by creating a blank template. Open the Corona Simulator and choose New Project from the File menu. Once you have the Create New Project window open, enter Highway Dodge as the project name, choose a blank template, and set the width to 400 and the height to 600. Leave the default orientation set to Upright.

Create New Project

After setting up your project, download the images for Highway Dodge. Create a new folder in your new project, name it images, and add the images to this folder. Your project should now look like this:

A Quick Look at the Project

2. Project Settings

With the project set up, let’s take a quick look at two important files, build.settings and config.lua.


This file handles the build time properties of the game. It stores information on the orientation of your app, icon information, iOS settings, and Android settings. The default setup is adequate for our game.


This configuration file controls the runtime properties of the game. This includes width, height, scale, fps (frames per second), and imageSuffix. The property we need to take a look at is imageSuffix. The imageSuffix property is used for dynamic image selection. In a nutshell, it tells the app to use a higher resolution image when on a higher resolution device.

I've provided high resolution images in the images folder so we need to update config.lua accordingly. Your project's config.lua file should look like the one below. I have omitted the push notification section, which is commented out.

3. Launch Point

With the project and dynamic image selection set up, let’s move on to main.lua. This file is the launch point of every app built with the Corona SDK. In our game, it’s going to hold three lines of code.

Step 1

The first line hides the status bar on iOS devices. Open main.lua and add the following line after the comment -- Your code here.

Step 2

Next, we start using composer by requiring the library into our game. We do this by adding the following line:

Step 3

Next, we use composer to move to the menu scene. We move scenes by calling the function composer.gotoScene(), passing the value "scene_menu" as the parameter. The value "scene_menu" is the name of the scene and the name of the file that we create in the next section.

A Word About Composer

Composer is the official scene management library of Corona. Composer allows developers to easily create a scene and transition between scenes. In two lines, I was able to transition from the main scene to the menu scene. If you would like to read more about Composer, visit Corona’s Composer Library Guide available on the Corona Labs Docs website.

4. Menu

The menu scene of our game will consist of only a couple of elements. The scene will hold a background graphic, a title, and a start button. We’ll be using Corona's built-in widget library to create the start button. The widget library allows us to quickly and easily create common user interface elements. In our game, we’ll be using it for the button creation only.

Step 1

In the project folder of Highway Dodge, create a new file, scene_menu.lua, and open it in your text editor of choice. Instead of starting from scratch, we are going to use the scene template available on the Corona Labs Docs website. With their template, we’ll be able to move a lot faster. Head over to Corona Labs Docs and copy/paste the scene template to scene_menu.lua.

Step 2

Add the widget library to our game by adding the following line, just below the composer library.

Step 3

We add our background using the graphics you downloaded earlier. The background should be positioned in the center of the screen. In the scene:create()  function and after the screenGroup variable is declared, add the following code:

Step 4

Next, we need to add the three lanes that represent the highway. We do this by using a table to hold the lanes and creating a for loop that runs three times. Place this snippet after the background graphic:

To make sure the lanes are always centered, I’ve placed the lanes on the x-axis using a bit of math. This ensures the lanes remain centered, regardless of the device the game runs on.

Step 5

We also add our logo for Highway Dodge by placing an image object near the top of the screen.

Step 6

Before we can add our button widget, we need to create a function that responds when the button is touched. We’ll name the function handleButtonEvent() and move the player to the game scene using composer.gotoScene(). We will only respond when the player has lifted their finger off the button or at the ended phase of the event.

Step 7

With the function added, we can add the button. We create the button by using widget.newButton and passing some values to it. We specify the width and height of the button, the image files for the button, the text to be displayed, the font type, the font size, and the font color.

We also tell Corona what function to call when the button is pressed and position it in the middle of the screen. The source files of this tutorial include comments that explain each of the values used to set up the button.

Step 8

To wrap up the menu scene, we need to remove the game scene when it exits. When Corona moves between scenes, it doesn’t always remove the previous scene. Without these lines, the game will always be in a game over scene after it’s been played once.

To remove the previous scene, we get the scene name and call composer.removeScene() to remove it if it exists. Add the following code to the scene:show() function.

5. Creating the Game Scene

We can now start working on the game scene. We’ll use the same workflow we used for creating the menu scene. Create a new file, scene_game.lua, and copy/paste the scene template available on Corona Labs Docs. Once you have the code in place, open scene_game.lua in your favorite text editor.

Step 1

To make coding the game scene easier for us, we are going to use the widget library and the physics library. The latter is used for collision detection. Add the following code to scene_game.lua:

On the first and second lines, we require the widget library and the physics library respectively. We then start physics and disable gravity. We don’t need gravity for our highway game, instead we’ll be using transition.to() to move the cars.

Step 2

In the scene:create() function, we declare a number of variables that we will use in the game. These variables will be responsible for the player car, lanes, enemy cars, and player score. To make things easier to read, I’ve added some comments.

Step 3

Below the variable declarations, we set up the functions for the game. We will implement each function in a later step. Add the following code after the variable declarations in the scene:create() function.

Step 4

After the functions, we add the background and lanes. For the lanes, we attach an event listener to each lane to make them respond to touch events. When touched, the listener calls the moveCar() function.

Step 5

With the background and lanes set up, it's time to create a text object to hold the player score and create the player car. The score will be at the top of the screen and the player car will be positioned on the leftmost lane. Additionally, we’ll make the player car a dynamic physics object.

Step 6

Next, we set a timer to send out a car based on the value of the sendEnemyFrequency variable and create a runtime event listener for global collisions.

6. Adding Game Functionality

We can finally add functionality to our game. This section will add additional code to each function we declared in the previous section. We’ll get started with incrementScore() and end with onGlobalCollision().


This function is called when an enemy car passes by the player and the transition is complete. When called, the player score is increased by 1. Add the following implementation to the incrementScore() function.


The moveCar() function is called when a lane is touched. On the ended phase of the event, we grab the lane identifier and move the car to the correct lane. We return true at the end to indicate a successful touch event. Add the following implementation to the moveCar() function.


The sendEnemyCar() function creates an enemy car, assigns the car to a lane, attaches a physics body to the car, and uses transition.to() to send the car towards the bottom of the screen. To get started, let’s create the enemy car object.

Next, we set the x and y location of the enemy car. We also create an if-then statement to assign the enemy car to the same lane the player car is in 50% of the time. This will force the player to move more often and makes the game more fun.

We also need to rotate the enemy car so it’s facing down and add a kinematic physics body type to the enemy car.

With the enemy car set up, we use the transition.to() function to send the enemy car down one of the lanes. When the transition is complete, the game calls a function to remove the object. I also increment the variable enemyCounter by 1 to keep track of the number of enemy cars in the game.

Finally, we want the game to get faster over time. For every other car that is sent, the game will recreate the timer and sets it to be 200ms faster.


The shortest function, onPlayAgainTouch(), returns the player to the main menu. This is what the implementation of the onPlayAgainTouch() function looks like.


The onGlobalCollision() function is used to detect collisions between any two physics objects on the screen. In our game, we only have two types of physics objects:

  • the player car
  • the enemy car

When these two objects collide, the game stops all timers, transitions, and event listeners. Additionally, the game displays a game over scene that allows the player to play again.

Step 1

First, we create an if-then statement that listens for the began phase.

Step 2

In the if-then statement, we stop the game. We pause all transitions, cancel the timer, pause physics (even if it’s not needed, it’s a good clean up call), and remove the event listener from all three lanes. Add the following code inside of the if-then statement:

Step 3

After the game mechanics have stopped, we add an opaque rectangle and a text object that says "Game Over!". This gives a good visual indication that the game has ended.

Step 4

To wrap up the global collision function, we add the play again button that sends the player back to the menu.

Test Drive

Run the application to see if everything is working as expected. You should be able to play the game, enemy cars should pop up from the top of the screen, and your score should increment for every enemy car you successfully dodge.


Thank you for reading my tutorial on creating Highway Dodge with the Corona SDK. You can download the source files for this game from GitHub. Take a moment to think how you can further improve the game. If you’re looking for some suggestions, I would recommend adding another lane, adding more enemy types, and even adding some cool power ups.

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.