Today’s guest tutorial comes to you courtesy of Greg Pugh. In addition to working as a Flash and mobile app developer for MC Strategies, Greg is the owner of GP Animations, an independent studio in Nanticoke, Pennsylvania. Greg’s apps include those listed on his blog here. Additionally, he writes Corona tutorials for RayWenderlich.com and Kwiksher.com. As a Corona Ambassador, Greg recently started to write an iBook that introduces new developers to the world of Corona SDK.
As a new parent, my iPad is quickly filling up with children’s books, games, and learning activity apps. Right now, my daughter seems to gravitate towards the two books I’ve written (http://www.ColinTurtle.com) and oddly enough, “Game For Cats.” Soon she will be the appropriate age for learning her shapes, colors, alphabet, etc. and she’ll want to use different apps. Today, I’m going to show you how to create a basic kids’ activity app where children can drag and drop shapes to the correct outlined area.
First, I suggest that you watch this video to see the app in action.
You’ll notice that you’re able to drag both shapes at the same time. I like this feature because kids have a tendency to use both their hands when playing on smart devices. In order to create this feature, you’ll utilize dmc_multitouch by David McCuskey (I’ve included the necessary module files in the project so you don’t have to download them). It should be noted that at the time of this writing, the Corona Simulator doesn’t support multitouch events. You will need to publish the completed project to test on an actual device in order to use multitouch.
You can download the project files here. Once the SnapShapes folder is unzipped, inside you’ll see two folders. SnapShapes_FINAL contains the completed main.lua file for you to try and SnapShapes_START just contains the artwork and supporting files.
To get started, open your text editor of choice, create a new file, and save it as main.lua in the SnapShapes_START folder you downloaded. The first step is to import the dmc_multitouch.lua file, so copy and paste the following code into main.lua:
-- Require dmc_multitouch MultiTouch = require("dmc_multitouch");
Next, you’ll hide the status bar since kids don’t seem to care about time or how much service your phone has.
-- Hide status bar display.setStatusBar(display.HiddenStatusBar);
Now you’ll insert the images provided to you in the images folder onto the display. Copy and paste the following into main.lua and then save.
-- Background image local background = display.newImageRect("images/background.png", 640, 960); background.x = display.contentCenterX; background.y = display.contentCenterY; -- Square outline local sqLine = display.newImageRect("images/sqLine.png", 228, 228); sqLine.x = 473; sqLine.y = 181; -- Square local square = display.newImageRect("images/square.png", 188, 188); square.x = 144; square.y = 778; -- Circle outline local circLine = display.newImageRect("images/circLine.png", 245, 245); circLine.x = 181; circLine.y = 180; -- circle positioning local circle = display.newImageRect("images/circle.png", 200, 200); circle.x = 473; circle.y = 778; -- myText positioning local myText = display.newImageRect("images/myText.png", 508, 78); myText.x = 311; myText.y = 475;
Open your Corona SDK Simulator, navigate to File > Open, browse for main.lua in your SnapShapes_START folder and open it for iPhone. Your Simulator will now look like the image at right.
Now that you’ve got all of the artwork displaying correctly, it’s time to add the functionality. First, you’ll create the code for the blue circle and once that’s done, it’s just a matter of changing variable names to the red square. You’ll need to activate multitouch for the circle and set initial positioning variables to 0. Copy and paste the following into your main.lua file:
-- Circle MultiTouch.activate(circle, "move", "single"); -- Set initial variables to 0 local circlePosX = 0; local circlePosY = 0;
When the circle is dragged, it will become the target of touch events such as “moved” and “ended.” If the circle is dragged within 50 pixels on the center of the circle outline, it should “snap” into the center of the outline. Otherwise it should just stay where the user drags it. Add the following code:
-- User drag interaction on blue circle local function circleDrag (event) local t = event.target -- If user touches & drags circle, follow the user's touch if event.phase == "moved" then circlePosX = circle.x - circLine.x; circlePosY = circle.y - circLine.y; if (circlePosX < 0) then circlePosX = circlePosX * -1; end if (circlePosY < 0) then circlePosY = circlePosY * -1; end -- If user drags circle within 50 pixels of center of outline, snap into middle if (circlePosX <= 50) and (circlePosY <= 50) then circle.x = circLine.x; circle.y = circLine.y; end
If the circle is snapped into the center of the outline and the user stops dragging it, the circle will permanently be placed in the middle of the outline. Add the following code:
-- When the stops dragging circle within 50 pixels of center of outline, snap into middle, and... elseif event.phase == "ended" then if (circlePosX <= 50) and (circlePosY <= 50) then circle.x = circLine.x; circle.y = circLine.y; -- ...lock circle into place where it cannot be moved. MultiTouch.deactivate(circle); end end return true; end
Finally, add an event listener for the circleDrag function and save:
When the Simulator refreshes, you will now be able to drag the circle around the screen, and when it is within 50 pixels of the outline, it will snap into place. If you stop dragging it after it’s in place, it will become permanently stuck.
Now it’s just a matter of adding the same code for the red square, so just substitute the variable names:
-- Same actions for the square as the circle MultiTouch.activate(square, "move", "single"); local squarePosX = 0; local squarePosY = 0; local function squareDrag (event) local t = event.target if event.phase == "moved" then squarePosX = square.x - sqLine.x; squarePosY = square.y - sqLine.y; if (squarePosX < 0) then squarePosX = squarePosX * -1; end if (squarePosY < 0) then squarePosY = squarePosY * -1; end if (squarePosX <= 50) and (squarePosY <= 50) then square.x = sqLine.x; square.y = sqLine.y; end elseif event.phase == "ended" then if (squarePosX <= 50) and (squarePosY <= 50) then square.x = sqLine.x; square.y = sqLine.y; -- If you'd like to be able to move the square again, comment out the line below MultiTouch.deactivate(square); end end return true; end square:addEventListener(MultiTouch.MULTITOUCH_EVENT, squareDrag);
You can comment out the “deactivate” line of code if you’d like users to be able to move the shapes even after they’ve put them in the correct locations. And, of course, you can add conditional statements to congratulate users when they’ve completed all the tasks.
And there you have it, a very quick and easy way to make an activity for children to play in an app!
The Next Step?
This basic concept can, of course, be expanded to suit other children-oriented or casual apps. For example:
- Use this same code to create a “dress up game” where children can place clothing on “dolls”.
- Create a puzzle game with many pieces, expanding the core function(s) to handle all pieces.
- Build a puzzle challenge into an adventure game.
As the mobile revolution continues, educational apps will likely grow in popularity. Understanding the basics behind a multitouch shape-match implementation is a first step towards building a great app that has the potential to be used not only at home, but in schools as well.