Need help with speed Matching Game logic

There are a ton of Corona templates online where you click on two tiles to uncover pairs of images. However, in the game below, not only are all the images already facing up, but the player(s) only have to click once on an image that is part of a pair. It’s a multiplayer game where the person who taps the correct image first wins.

http://www.youtube.com/watch?v=gLhrOfpEYQU

Any idea how to accomplish this in code?

Thanks for any help.

  1. Display objects in random locations on the screen.

  2. Create an extra property for each display object, such as obj.winner = true|false

  3. Add event listeners to each object.

  4. In the listener function, check to see whether the object that was tapped was a winner.

4a. If winner, add a point to the correct player based on where the object was tapped (which side).

4b. If loser, subtract a point based on where the object was tapped.

  1. Repeat until the level is over (someone gets 10 points).

If you know these API calls:

display.newImage

addEventListener

…you should be able to make that game.

 Jay

Thanks Jay,

Definitely a good starting point. So far I have it based on this existing Matching Game template:

http://code.tutsplus.com/tutorials/corona-sdk-create-a-memory-match-game–mobile-7271

In the template, the images are buttons in a fixed array; I may eventually abandon this route completely in lieu of random coordinates, but I was able to use some of your suggestions. 

I will probably be asking more questions, so please bear with me.

Thx

Jay.

Your algorithm explained the way to do this game nicely. But how to make the pictures randomly distributed on the screen especially when it comes to more than one player. .

Also how make the movement when the answer is correct . How to make pictures move nicely in this way to certain point …

Thx
Abdul

To place images randomly on the screen you’ll use math.random() – and since you can give it a minimum and maximum, you can easily limit them to a corner of the screen or just one side. For example:

for x = 1, 5 do local xPos = math.random(centerX, screenRight) local yPos = math.random(screenTop, centerY) local circ = display.newCircle(xPos, yPos, 30) end

Assuming you have variables set up for centerX, screenRight, etc., that code will put 5 circles in random locations of the upper-right corner of the screen. (Note: that’s not optimized code, just quick and dirty.)

For movement of the images you’ll want to use transition.to() – here’s a doc page that talks all about the options:

http://docs.coronalabs.com/guide/media/transitionLib/index.html

Moving the image that was tapped will be easy, but you’ll have to have a way to find the matching image to move it as well. But get the one that was tapped moving to the center of the play area and then work on moving the other one.

Sorry I don’t have time to give you more details. I hope that helps.

 Jay

Thanks guys.

If you’re interested, here’s how I ended up doing the random object spawning. There’s probably better (and less verbose) ways to do this, but this worked for me. I’m actually almost done with the game :slight_smile:

-- Nonmatching png table local imgs = {      "images/ball.png",     "images/camera.png",       "images/dice.png",      "images/fan.png",      "images/goose.png",     "images/hat.png",      "images/marble.png",     "images/orange.png",     "images/pear.png",     "images/radish.png",     "images/strawberry.png"   } nonMatchImageContainer = {} -- initialize nonmatching array local numOfImages = math.random(6,12) --spawn between 6 and 12 random objects on screen for i=1,numOfImages do -- loop to go from 1 to total number of images          nonMatchImageContainer[i] = display.newImage(imgs[i])  -- create a new Rect for each item in loop     -- randomize item's location on screen but keep within screen's boundaries     nonMatchImageContainer[i].x = math.random(50, display.contentWidth - 50)      nonMatchImageContainer[i].y = math.random(50, display.contentHeight - 50)        nonMatchImageContainer[i]:addEventListener("tap", buttonListener2) -- make each item a button     nonMatchImageContainer[i]:scale(.5,.5)     nonMatchImageContainer[i]:rotate(math.random(-270,270)) --give each object a random initial rotation     physics.addBody(nonMatchImageContainer[i], "dynamic", {radius = 55, density = 1.0, friction = 50, bounce = 100, isSensor = false})     nonMatchImageContainer[i].name = "nonmatchingitem"     nonMatchImageContainer[i].postCollision = onOverlap     nonMatchImageContainer[i]:addEventListener("postCollision", nonMatchImageContainer[i])     group:insert(nonMatchImageContainer[i]) end

onOverlap is just a method I call to prevent the objects from displaying on top of each other.

local onOverlap = function(self, event)    if event.force \> 1 and not self.isHit then         if event.other.myName == "nonmatchingitem" then --reposition item elsewhere             nonMatchImageHolder[i].x = math.random(85, display.contentWidth - 85)             nonMatchImageHolder[i].y = math.random(75, display.contentHeight - 180)             print("Moved overlapping object")         end    end end

Thanks Jay and marlom,

it looks there many stuff behind transition and easing :slight_smile: still i could not simulate the same movement they did in the game… 

also few questions …

  • why do we need physics in this case ?

-Marlon : i didn’t see where do you put the matching picture on the screen. i saw only the non matching ones only. 

i trying your code and i was able post them on the screen. i think you need to have two different sizes of picture if you plan to design for ipad for example. i think your size is 50x50 for each object … correct?

thx

Abdulaziz

We use physics because it keeps the objects from touching each other. “Static” means the spawned object stays in place; “dynamic” enables it to move if it collides with another object. It’s handy because you can set a radius value that gives each item its own personal space.

For the matching images, I ended up pulling those from a separate table altogether. It’s kludgy, but I did this because I knew that I was going to include a two player version. 

I only worry about the 2x images for the application bundle (icons, App Store graphics, etc). For in-game assets, I usually just start out with a high-res image to begin with, then just scale down using :scale( x%, y%). Do a Google search for ultimate config.lua file, and it should take care of the rest (at least for iOS).

local matchingimages = {    ...your objects } randomMatchImage = matchingimages[math.random(#matchingimages)] --pick 1 item from matchingimages table above filename1 = randomMatchImage filename2 = filename1 --make filename2 a copy of filename1 math.randomseed(os.time()) local function showMatchItem1()     item1 = display.newImage(filename1)     item1:scale(.2, .2)     item1.x, item.y = etc... --spawn on left half of screen end              local function showMatchItem2()      item2 = display.newImage(filename2)     item2:scale(.2, .2)     item1.x, item.y = etc... --spawn on right half of screen end              showMatchItem1() showMatchItem2()  

  

Thanks marlon,

i will bother you with more questions :slight_smile:

1- so you have two sets of images … one for matching and one for non matching. ?? is this because you dont want to repeat the images between sets. 

2-for physics : still not clear… how do you start them as dynamic ?? normally they fall down if you do so ??

3- how they make the effect around the selected object when you click the right match ? i mean the bubble ones ?

regards

Abdul

I used two separate arrays for organizational purposes. When I first started building my game, I wasn’t sure how to create the loop to exclude the images that were already used. But you can also use something like this to generate a matching pair instead:

local function makeMatchingPair()

    local thing = display.newImageRect(“ball.png”, 50, 50)

    thing.x, thing.y = math.random(30, 400), math.random(50, display.contentHeight-50)

end

 

timer.performWithDelay(0, makeMatchingPair, 2) --2 here means spawn two of them

Your physics objects only fall down if you invoke the physics.setGravity() method and enter some values for it. Otherwise, even when a physics object is designated as “dynamic”, it will stay put unless affected by other nearby objects.

There is a nice sparkle effect on the page below. You just attach it to the buttonlistener at event.x and event.y

https://developer.coronalabs.com/code/simple-particle-emitter-and-fireworks-show

Thabks sir for sharing the info.
So I should not start the physics … correct?
I tried to include physics wihout
physics.setGravity() but still they fall down.
Thx
Abdul

My bad. You do need to setGravity but it needs to look like this:

physics.setGravity(0, 0)

no issue sir :slight_smile: … thanks for you help…

i will play with the code and see how it will work  :)

regards

Abdul

Here’s one for you, Jay.

In making my two player version, I am using the same logic to distribute the objects around screen as in the 1-player version. I have a vertical line (also a physics object) down the middle of the screen that splits the screen in two.

My problem is sometimes it only spawns one item on the lefthand (Player 1) side, but then the rest of the objects on the righthand (Player 2) side, and vice versa. Any idea how to distribute them more evenly across both sides using code? As you know, I am randomly generating objects using this code from an earlier post above:

nonMatchImageContainer[i].x = math.random(50, display.contentWidth - 50)  nonMatchImageContainer[i].y = math.random(50, display.contentHeight - 50)

Thanks,

Marlon

  1. Display objects in random locations on the screen.

  2. Create an extra property for each display object, such as obj.winner = true|false

  3. Add event listeners to each object.

  4. In the listener function, check to see whether the object that was tapped was a winner.

4a. If winner, add a point to the correct player based on where the object was tapped (which side).

4b. If loser, subtract a point based on where the object was tapped.

  1. Repeat until the level is over (someone gets 10 points).

If you know these API calls:

display.newImage

addEventListener

…you should be able to make that game.

 Jay

Thanks Jay,

Definitely a good starting point. So far I have it based on this existing Matching Game template:

http://code.tutsplus.com/tutorials/corona-sdk-create-a-memory-match-game–mobile-7271

In the template, the images are buttons in a fixed array; I may eventually abandon this route completely in lieu of random coordinates, but I was able to use some of your suggestions. 

I will probably be asking more questions, so please bear with me.

Thx

Jay.

Your algorithm explained the way to do this game nicely. But how to make the pictures randomly distributed on the screen especially when it comes to more than one player. .

Also how make the movement when the answer is correct . How to make pictures move nicely in this way to certain point …

Thx
Abdul

To place images randomly on the screen you’ll use math.random() – and since you can give it a minimum and maximum, you can easily limit them to a corner of the screen or just one side. For example:

for x = 1, 5 do local xPos = math.random(centerX, screenRight) local yPos = math.random(screenTop, centerY) local circ = display.newCircle(xPos, yPos, 30) end

Assuming you have variables set up for centerX, screenRight, etc., that code will put 5 circles in random locations of the upper-right corner of the screen. (Note: that’s not optimized code, just quick and dirty.)

For movement of the images you’ll want to use transition.to() – here’s a doc page that talks all about the options:

http://docs.coronalabs.com/guide/media/transitionLib/index.html

Moving the image that was tapped will be easy, but you’ll have to have a way to find the matching image to move it as well. But get the one that was tapped moving to the center of the play area and then work on moving the other one.

Sorry I don’t have time to give you more details. I hope that helps.

 Jay

Thanks guys.

If you’re interested, here’s how I ended up doing the random object spawning. There’s probably better (and less verbose) ways to do this, but this worked for me. I’m actually almost done with the game :slight_smile:

-- Nonmatching png table local imgs = {      "images/ball.png",     "images/camera.png",       "images/dice.png",      "images/fan.png",      "images/goose.png",     "images/hat.png",      "images/marble.png",     "images/orange.png",     "images/pear.png",     "images/radish.png",     "images/strawberry.png"   } nonMatchImageContainer = {} -- initialize nonmatching array local numOfImages = math.random(6,12) --spawn between 6 and 12 random objects on screen for i=1,numOfImages do -- loop to go from 1 to total number of images          nonMatchImageContainer[i] = display.newImage(imgs[i])  -- create a new Rect for each item in loop     -- randomize item's location on screen but keep within screen's boundaries     nonMatchImageContainer[i].x = math.random(50, display.contentWidth - 50)      nonMatchImageContainer[i].y = math.random(50, display.contentHeight - 50)        nonMatchImageContainer[i]:addEventListener("tap", buttonListener2) -- make each item a button     nonMatchImageContainer[i]:scale(.5,.5)     nonMatchImageContainer[i]:rotate(math.random(-270,270)) --give each object a random initial rotation     physics.addBody(nonMatchImageContainer[i], "dynamic", {radius = 55, density = 1.0, friction = 50, bounce = 100, isSensor = false})     nonMatchImageContainer[i].name = "nonmatchingitem"     nonMatchImageContainer[i].postCollision = onOverlap     nonMatchImageContainer[i]:addEventListener("postCollision", nonMatchImageContainer[i])     group:insert(nonMatchImageContainer[i]) end

onOverlap is just a method I call to prevent the objects from displaying on top of each other.

local onOverlap = function(self, event)    if event.force \> 1 and not self.isHit then         if event.other.myName == "nonmatchingitem" then --reposition item elsewhere             nonMatchImageHolder[i].x = math.random(85, display.contentWidth - 85)             nonMatchImageHolder[i].y = math.random(75, display.contentHeight - 180)             print("Moved overlapping object")         end    end end

Thanks Jay and marlom,

it looks there many stuff behind transition and easing :slight_smile: still i could not simulate the same movement they did in the game… 

also few questions …

  • why do we need physics in this case ?

-Marlon : i didn’t see where do you put the matching picture on the screen. i saw only the non matching ones only. 

i trying your code and i was able post them on the screen. i think you need to have two different sizes of picture if you plan to design for ipad for example. i think your size is 50x50 for each object … correct?

thx

Abdulaziz