Corona SDK: Create a Whack-a-Mole Game – Adding Interactivity

Corona SDK: Create a Whack-a-Mole Game – Adding Interactivity

Tutorial Details
  • Technology: Corona SDK
  • Difficulty: Intermediate
  • Completion Time: 30 - 60 Minutes (Estimated)

This is the second installment in our Corona SDK Whack A Mole tutorial. In today’s tutorial, we’ll add to our interface and start coding 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: Load Sounds

Sound effects used in the game will be loaded at start. This will make them ready for play immediately.

local hit = audio.loadSound('hit.wav')

Step 2: Variables

These are the variables we’ll use. Read the comments in the code to know more about them. Some of their names are self explanatory, so there will be no further comment there.

local timerSource
local currentWorms = 0 --worms already shown
local wormsHit = 0
local totalWorms = 10 --total worms to hit

Step 3: Declare Functions

Declare all functions as local at the start.

local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local prepareWorms = {}
local startTimer = {}
local showWorm = {}
local popOut = {}
local wormHit = {}
local alert = {}

Step 4: Constructor

Next we’ll create the function that will initialize all the game logic:

function Main()
	--code
end

Step 5: Add the Title View

Now we place the TitleView on the stage and call a function that will add the tap listeners to the buttons.

function Main()
	titleBg = display.newImage('titleBg.png')
	playBtn = display.newImage('playBtn.png', display.contentCenterX - 25.5, display.contentCenterY + 40)
	creditsBtn = display.newImage('creditsBtn.png', display.contentCenterX - 40.5, display.contentCenterY + 85)
	titleView = display.newGroup(titleBg, playBtn, creditsBtn)
	startButtonListeners('add')
end

Step 6: Start Button Listeners

This function adds the necesary listeners to the TitleView buttons.

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

Step 7: Show Credits

The credits screen is shown when the user taps the credits button. A tap listener is added to the credits view to remove it.

function showCredits:tap(e)
	playBtn.isVisible = false
	creditsBtn.isVisible = false
	creditsView = display.newImage('creditsView.png')
	transition.from(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:addEventListener('tap', hideCredits) creditsView.x = creditsView.x - 0.5 end})
end

Step 8: Hide the Credits

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

function hideCredits:tap(e)
	playBtn.isVisible = true
	creditsBtn.isVisible = true
	transition.to(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
end

Step 9: Show Game View

When the Play button is tapped, the title view is tweened and removed revealing the game view. The score text is added in this step too.

function showGameView:tap(e)
	transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
	score = display.newText('0' .. '/' .. totalWorms, 58, 6, native.systemFontBold, 16)
	score:setTextColor(238, 238, 238)
	prepareWorms()
end

Step 10: Prepare Worms

The following function creates and places the worms in the stage. We hide them later and add a tap listener to each one.

function prepareWorms()
	w1 = display.newImage('worm.png', 80.5, 11)
	w2 = display.newImage('worm.png', 198.5, 51)
	w3 = display.newImage('worm.png', 338.5, 34)
	w4 = display.newImage('worm.png', 70.5, 110)
	w5 = display.newImage('worm.png', 225.5, 136)
	w6 = display.newImage('worm.png', 376.5, 96)
	w7 = display.newImage('worm.png', 142.5, 211)
	w8 = display.newImage('worm.png', 356.5, 186)
	worms = display.newGroup(w1, w2, w3, w4, w5, w6, w7, w8)
	for i = 1, worms.numChildren do
		worms[i]:addEventListener('tap', wormHit)
		worms[i].isVisible = false
	end
	startTimer()
end

Step 11: Code Review

Here is the full code written in this tutorial alongside with comments to help you identify each part:

-- Whack A Worm Game
-- Developed by Carlos Yanez
-- Hide Status Bar
display.setStatusBar(display.HiddenStatusBar)
-- Import MovieClip
local movieclip = require('movieclip')
-- Graphics
-- [Background]
local bg = display.newImage('gameBg.png')
-- [Title View]
local titleBg
local playBtn
local creditsBtn
local titleView
-- [Credits]
local creditsView
-- [Score]
local score
-- [Worms]
local w1
local w2
local w3
local w4
local w5
local w6
local w7
local w8
local worms
local lastWorm = {}
-- Load Sound
local hit = audio.loadSound('hit.wav')
-- Variables
local timerSource
local currentWorms = 0
local wormsHit = 0
local totalWorms = 10
-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local prepareWorms = {}
local startTimer = {}
local showWorm = {}
local popOut = {}
local wormHit = {}
local alert = {}
-- Main Function
function Main()
	titleBg = display.newImage('titleBg.png')
	playBtn = display.newImage('playBtn.png', display.contentCenterX - 25.5, display.contentCenterY + 40)
	creditsBtn = display.newImage('creditsBtn.png', display.contentCenterX - 40.5, display.contentCenterY + 85)
	titleView = display.newGroup(titleBg, playBtn, creditsBtn)
	startButtonListeners('add')
end
function startButtonListeners(action)
	if(action == 'add') then
		playBtn:addEventListener('tap', showGameView)
		creditsBtn:addEventListener('tap', showCredits)
	else
		playBtn:removeEventListener('tap', showGameView)
		creditsBtn:removeEventListener('tap', showCredits)
	end
end
function showCredits:tap(e)
	playBtn.isVisible = false
	creditsBtn.isVisible = false
	creditsView = display.newImage('creditsView.png')
	transition.from(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:addEventListener('tap', hideCredits) creditsView.x = creditsView.x - 0.5 end})
end
function hideCredits:tap(e)
	playBtn.isVisible = true
	creditsBtn.isVisible = true
	transition.to(creditsView, {time = 300, x = -creditsView.width, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
end
function showGameView:tap(e)
	transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
	score = display.newText('0' .. '/' .. totalWorms, 58, 6, native.systemFontBold, 16)
	score:setTextColor(238, 238, 238)
	prepareWorms()
end
function prepareWorms()
	w1 = display.newImage('worm.png', 80.5, 11)
	w2 = display.newImage('worm.png', 198.5, 51)
	w3 = display.newImage('worm.png', 338.5, 34)
	w4 = display.newImage('worm.png', 70.5, 110)
	w5 = display.newImage('worm.png', 225.5, 136)
	w6 = display.newImage('worm.png', 376.5, 96)
	w7 = display.newImage('worm.png', 142.5, 211)
	w8 = display.newImage('worm.png', 356.5, 186)
	worms = display.newGroup(w1, w2, w3, w4, w5, w6, w7, w8)
	for i = 1, worms.numChildren do
		worms[i]:addEventListener('tap', wormHit)
		worms[i].isVisible = false
	end
	startTimer()
end

Next Time…

In the next and final part of the series, we’ll handle the worms animation, tap events to ‘hit’ the worm, and the final steps to take prior to app release, like app testing, creating a start screen, adding an icon and, finally, building the app. Stay tuned for the final part!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Ryan

    Great tutorial. Anxious for the final part!

  • russ

    Thanks I learned something new when you inserted the images in () at end of the display.newGroup.

    I would have done worms:insert(w1)
    worms:insert(w2) etc… which would have been 8x longer. thanks for the tip!

    I