Posted on by

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.

Preface

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.

Project Code

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;

childrens-app-1Open 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:

circle:addEventListener(MultiTouch.MULTITOUCH_EVENT, circleDrag);

childrens-app-2When 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.


Posted by . Thanks for reading...

18 Responses to “Tutorial: Basic Shape-Matching App”

  1. James

    This tutorial came just in time for us. We’ll be basing our next app – a dress up game, on this very tutorial. Just wanted to say thanks guys, you really helped us on this one!!

    Reply
  2. Morten

    Thank you for this tutorial. I’m currently making a puzzle for kids and was trying to find a more generic approach for comparing the source and destination. It turned out the answer was right in front of me once I saw your tutorial. Thanks!

    Reply
  3. russell

    The way it was written made it very easy to understand. You have planted a seed that allow us developers may grow a plant or beanstalk ang grow our own beans.

    Reply
  4. Latchmanan

    Thanks for sharing your knowledge, Rob. I’d like to build my first game (puzzle) based on your code above. I’m in the middle of integrate your code with Conona’s storyboard module. However, I’m seeing a small blue and red squares at top left of my screen. But no errors on the console. As my troubleshoot, I’ve removed all code except the include line – require(“dmc_multitouch”). Any hints or advice pls? Thank you again.

    Reply
  5. hamid

    Thanks for the tutorial
    Could anyone advise me how to code an additional feature whereby you can duplicate the draggable shape by double clicking it for example? Thanks

    Reply
  6. Multitouch

    Hi, very usefull tutorial, but I noticed a problem, I.E. if you click on circle without moving it going automatically to line, how to fix this.

    Thank You

    Reply
  7. Multitouch

    Hi, I found the problem:
    Problem was at X and Y position, because in this default position as it is the IF condition is always true, so if you want to fix this problem, just remove the ending part from code, and IF Condition will work only on moved event.

    Thank You

    Reply
    • Ricky

      Hi, exactly which lines did you remove from the “local function squareDrag (event)” function? I have the same problem!
      Thanks,
      Ricky.

      Reply
  8. Erin

    Hi! I am working on a game for a Grad Class and it is very similar to what you have here. Your tutorial actually helped me build some of the code. However, I am wanting a “Good Job!” screen to appear once they have the letters (or in your case shapes) in the right places. I have tried several methods, but nothing seems to be working. I am trying to use the storyboard API. Any tips or advice would be helpful!

    Reply

Leave a Reply

  • (Will Not Be Published)