This is the second installment in the Corona SDK Match Shapes tutorial. In today’s tutorial, we’ll add to the interface and game interaction by programming the shape matching algorithm. Read on!
Also available in this series:
- Build a Match Shapes Game - Interface Creation
- Build a Match Shapes Game - Adding Interaction
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 necessary 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 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 it.
function showCredits:tap(e)
playBtn.isVisible = false
creditsBtn.isVisible = false
creditsView = display.newImage('credits.png', 0, display.contentHeight)
transition.to(creditsView, {time = 300, y = display.contentHeight - 25, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})
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)
transition.to(creditsView, {time = 300, y = display.contentHeight + 25, onComplete = function() creditsBtn.isVisible = true playBtn.isVisible = true creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
end
Step 4: Show Game View
When the Play 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)
transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})
Step 5: Game Background
This code places the game background image in the stage.
-- Game Background
gameBg = display.newImage('gameBg.png', 10, 350)
Step 6: Place Holders
The Place Holders are background graphics used to represent where the actual shapes should be dragged to. The next lines create them and place them in the stage.
-- Place holders
sHolder = display.newImage('sHolder.png', 15, 130)
pHolder = display.newImage('pHolder.png', 115, 130)
tHolder = display.newImage('tHolder.png', 215, 130)
Step 7: Instructions
An instructions message will be animated when the game starts. You can change the time it appears by changing the performWithDelay() code.
-- Instructions
ins = display.newImage('instructions.png', 45, 270)
transition.from(ins, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(2000, function() transition.to(ins, {time = 200, alpha = 0.1, onComplete = function() display.remove(ins) ins = nil end}) end) end})
Step 8: Shapes
The shapes that will be used are created in the next few lines of code.
-- Shapes
square = display.newImage('square.png', 240, 386)
pentagon = display.newImage('pentagon.png', 32, 386)
triangle = display.newImage('triangle.png', 131, 386)
square.name = 'square'
pentagon.name = 'pentagon'
triangle.name = 'triangle'
gameListeners()
end
Step 9: Game Listeners
This function adds the necessary listeners to start the game logic.
function gameListeners()
function gameListeners()
square:addEventListener('touch', dragShape)
triangle:addEventListener('touch', dragShape)
pentagon:addEventListener('touch', dragShape)
end
Step 10: Hit Test Objects
We'll use an excellent and useful function for collision detection without physics. You can find the original example and source at CoronaLabs Code Exchange.
function hitTestObjects(obj1, obj2)
local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin
local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax
local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin
local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax
return (left or right) and (up or down)
end
Step 11: Drag Shapes
This is the principal function of this game, it handles the object dragging by checking the object's position and moving it to the event position.
function dragShape(e) if(e.phase == 'began') then lastX = e.x - e.target.x lastY = e.y - e.target.y elseif(e.phase == 'moved') then e.target.x = e.x - lastX e.target.y = e.y - lastY
Step 12: Square Collision
This last function also contains code that checks if the shape is in the correct spot. This is the square part.
elseif(e.target.name == 'square' and e.phase == 'ended' and hitTestObjects(e.target, sHolder)) then
e.target.x = 60.5
e.target.y = 175
e.target:removeEventListener('touch', dragShape)
correct = correct + 1
audio.play(correctSnd)
Step 13: Triangle Collision
The same method is used for the triangle. If the correct shape is placed in the correct spot, the shape drag listener is removed.
elseif(e.target.name == 'triangle' and e.phase == 'ended' and hitTestObjects(e.target, tHolder)) then
e.target.x = 260
e.target.y = 169
e.target:removeEventListener('touch', dragShape)
correct = correct + 1
audio.play(correctSnd)
Step 14: Pentagon Collision
This is the pentagon part. If the right shape touches the right spot when the touch event ends, the shape aligns to the center of the placeholder.
elseif(e.target.name == 'pentagon' and e.phase == 'ended' and hitTestObjects(e.target, pHolder)) then
e.target.x = 160
e.target.y = 172
e.target:removeEventListener('touch', dragShape)
correct = correct + 1
audio.play(correctSnd)
end
Step 15: Check for Completion
Finally, we'll check if the three shapes have been placed correctly, and then play a sound and call an alert if it is correct.
if(e.phase == 'ended' and correct == 3) then audio.stop() audio.play(winSnd) alert() end end
Step 16: Alert
The alert function creates an alert view, animates it, and ends the game.
function alert()
alertView = display.newImage('win.png', 95, 270)
transition.from(alertView, {time = 200, alpha = 0.1})
end
Step 17: Call Main Function
In order to start the game, the Main function needs to be called. With the above code in place, we can do that here:
Main()
Step 18: Loading Screen

The Default.png file is an image that is displayed 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 automatically be added by the Corona compiler.
Step 19: Icon

Using the graphics created previously you can now create a nice 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 transparent glare, iTunes and the iPhone will do that for you.
Step 20: Testing in Simulator

It's time for 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 last step!
Step 21: 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!
Conclusion
In this series you learned about object dragging and collision detection without using the physics engine. This may reduce your app memory consumption and increase the performance. You can experiment with the final result and try to make your custom version of the game!
I hope you enjoyed this tutorial series and found it helpful. Thank you for reading!
Comments