Corona SDK

Create a Lunar Lander Inspired Game – Adding Interaction


This is the second installment in our Corona SDK Lunar Lander tutorial. In today’s tutorial, we’ll add to our interface and the game interaction. Read on!

Where We Left Off. . .

Please be sure to check part 1 of the series to fully understand and prepare for this tutorial.

Step 1: Start Button Listeners

This function adds the necesary listeners to the TitleView buttons:

function startButtonListeners(action)
	if(action == 'add') then
		titleBg:addEventListener('tap', showGameView)
		creditsBtn:addEventListener('tap', showCredits)
		titleBg:removeEventListener('tap', showGameView)
		creditsBtn:removeEventListener('tap', showCredits)

Step 2: Show Credits

The credits screen is shown when the user taps the about button, a tap listener is added to the credits view to remove this.

function showCredits:tap(e)
	creditsBtn.isVisible = false
	creditsView = display.newImage('credits.png', -130, display.contentHeight-140), {time = 300, x = 65, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})

Step 3: Hide Credits

When the credits screen is tapped, it'll be tweened out of the stage and removed.

function hideCredits:tap(e)
	creditsBtn.isVisible = true, {time = 300, y = display.contentHeight+creditsView.height, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})

Step 4: Show the Game View

When the Start button is tapped, the title view is tweened and removed revealing the game view. There are many parts involved in this view, so we'll split them in the next steps.

function showGameView:tap(e), {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})

Step 5: Add Moons

This code places the moons in the stage.

-- Moons
m1 = display.newImage('moon.png', 386, 156)
m2 = display.newImage('moon.png', 252, 99)
m3 = display.newImage('moon.png', 131, 174) = 'moon' = 'moon' = 'moon'

Step 6: Big Moon

A bigger moon is used as the landing spot. Use the next code to place it:

-- Big Moon
bigM = display.newImage('moonBig.png', 10, 53) = 'moon'

Step 7: Landing Spot

The landing spot is represented by an arrow graphic. A name property is created to help identify these elements when a collision occurs.

-- Arrow
arrow = display.newImage('arrow.png', 44, 24) = 'goal'

Step 8: Rocket

Next, we add the rocket. This will be our user-controlled element.

-- Rocket
rocket = display.newImage('rocket.png', 409.5, 114)

Step 9: Stars

The following code will place the stars on the screen:

-- Stars
s1 = display.newImage('star.png', 341, 146)
s2 = display.newImage('star.png', 273, 48)
s3 = display.newImage('star.png', 190, 234)
s4 = display.newImage('star.png', 37, 135) = 'star' = 'star' = 'star' = 'star'

Step 10: Controls

In order to move the Rocket in the screen we'll need a game pad, this code will take care of that. A tap listener will be added later to each button to handle the movement.

  -- Controls
  up = display.newImage('dirBtn.png', 404, 246)
  left = display.newImage('dirBtn.png', 10, 246)
  right = display.newImage('dirBtn.png', 84, 246) = 'up' = 'left' = 'right'
  up.rotation = 90
  right.rotation = 180

Step 11: Add Physics

Here we add the physics to the graphic elements.

-- Add Physics
physics.addBody(m1, 'static', {radius = 35})
physics.addBody(m2, 'static', {radius = 35})
physics.addBody(m3, 'static', {radius = 35})
physics.addBody(bigM, 'static', {radius = 40})
physics.addBody(arrow, 'static')
physics.addBody(rocket, 'dynamic')
rocket.isFixedRotation = true
rocket.isAwake = false --prevents initial explosion sound
physics.addBody(s1, 'static', {radius = 12})
physics.addBody(s2, 'static', {radius = 12})
physics.addBody(s3, 'static', {radius = 12})
physics.addBody(s4, 'static', {radius = 12})
arrow.isSensor = true
s1.isSensor = true
s2.isSensor = true
s3.isSensor = true
s4.isSensor = true

Step 12: Game Listeners

This function adds the necessary listeners to start the game logic.

function gameListeners()
	up:addEventListener('touch', movePlayer)
	left:addEventListener('touch', movePlayer)
	right:addEventListener('touch', movePlayer)
	Runtime:addEventListener('enterFrame', update)
	rocket:addEventListener('collision', onCollision)

Step 13: Move Player Function

The direction variable is changed by this function, this will make the rocket go in the pressed direction.

function movePlayer(e)
	if(e.phase == 'began' and == 'up') then
		dir = 'up'
	elseif(e.phase == 'ended' and == 'up') then
		dir = 'none'
	elseif(e.phase == 'began' and == 'left') then
		dir = 'left'
	elseif(e.phase == 'began' and == 'right') then
		dir = 'right'
	elseif(e.phase == 'ended' and == 'left') then
		dir = 'none'
	elseif(e.phase == 'ended' and == 'right') then
		dir = 'none'

Step 14: Rocket Movement

These lines move the rocket according to the direction stablished by the movePlayer function created in step 13.

function update(e)
	-- Rocket Movement
	if(dir == 'up') then
		rocket:setLinearVelocity(0, -80)
	elseif(dir == 'left') then
			rocket:setLinearVelocity(-100, 0)
	elseif(dir == 'right') then
			rocket:setLinearVelocity(100, 0)

Step 15: Rocket-Moon Collision

The next code listens for a variable set to true when a collision occurs between the rocket and a moon, the variable value is changed by the onCollision function that will be created later.

When true, the rocket will be placed at its original position and put into an sleep state to prevent a collision with the moon under it.

-- Rocket-Moon Collision
if(hitMoon) then
	rocket.x = 421.5
	rocket.y = 134
	hitMoon = false
	rocket.isAwake = false

Step 16: Rocket-Star Collision

A similar method is used in the rocket-star collision detection.

-- Rocket-Star Collision
if(hitStar) then
	stars = stars + 1
	hitStar = false

Step 17: Landing Point Collision

The level will be complete when the player has collected the four stars and lands on the bigger moon. The following code handles that.

-- Goal
if(hitGoal and stars == 4) then
	rocket.x = 52
	rocket.y = 35
	hitGoal = false
	complete = display.newImage('complete.png')
elseif(hitGoal and stars ~= 4) then
	hitGoal = false

Step 18: Collision Function

This function runs when the rocket collides with another body. The name of the body is then checked to perform the right action. Basically, a sound is played and a variable is set to true (for the update function to see) according to the other body name.

function onCollision(e)
	if( == 'moon') then
		hitMoon = true
	elseif( == 'star') then
		starHit = e.other
		hitStar = true
	elseif( == 'goal') then
		hitGoal = true

Step 19: Call Main Function

In order to start the game, the Main function needs to be called. With the above code in place, we'll do that here:


Step 20: Loading Screen

The Default.png file is an image that will be displayed right when you start the application while the iOS loads the basic data to show the Main Screen. Add this image to your project source folder, it will be automatically added by the Corona compliler.

Step 21: Icon

Using the graphics you created before you can now create a nice and good looking icon. The icon size for the non-retina iPhone icon is 57x57px, but the retina version is 114x114px and the iTunes store requires a 512x512px version. I suggest creating the 512x512 version first and then scaling down for the other sizes.

It doesn't need to have the rounded corners or the transparent glare, iTunes and the iPhone will do that for you.

Step 22: Testing in Simulator

It's time to do the final test. Open the Corona Simulator, browse to your project folder, and then click open. If everything works as expected, you are ready for the final step!

Step 23: Build

In the Corona Simulator go to File > Build and select your target device. Fill the required data and click build. Wait a few seconds and your app will be ready for device testing and/or submission for distribution!


Experiment with the final result and try to make your custom version of the game!

I hope you liked this tutorial series and find it helpful. Thank you for reading!

Related Posts