Tracking Flipped Cards
Once a card has been clicked on and flipped over, you need to prevent it from being clicked on again. Checking the card's rotation would probably work, but you also need to be able to know when two cards have been flippedso they can be removed from play if a match was found, or flipped back over if no match was found.The easiest way to track the cards is to use a list. In this section you'll use a linear list to track the pairs of cards being flipped over. Let's begin by adding the flippedList property, and then initializing it to an empty list.
|1. ||If the game script behavior is not open, right-click the 3D sprite and select Script from the context menu. Add the property declaration for flippedList to the top of the script:|
|2. ||Initialize the list to an empty list within the beginSprite handler, as shown:|
You can place the line to initialize flippedList as the last line in the handler, after the line that calls assignTextures().You now need to add a further conditional test within the mouseUp handler. After getting the model's number (from 1 to 16) and storing it in modNumber, you want to see if that number is contained in flippedList. If it isn't, the model hasn't been flipped, so you can add the number to flippedList, create the transforms, set isRotating to 1, etc.
flippedList = 
|3. ||Add the following two lines of code within the mouseUp handler. Add them immediately after the line that sets modNumber to the model's number:|
Note that these two lines should also come immediately before the line that sets isRotating = 1.If the model's number is not in the flippedList, it will be added to it before the model is flipped. The next time you try to click on the model, the test will fail because the model's number is contained in the flippedList. With this test in place, each card can only be flipped once.Let's test this out and see how it's working.
if not(flippedList.getOne(modNumber)) then
|4. ||Add the corresponding end if statement to the end of the handler. Logically, it comes directly after the line that sets transformPercent = 0, but you can also place it as the very last line, before the end statement.Remember, you can press the Tab key within the script window and your code will be auto-indented. This makes it easy to spot missing or malformed end if statements.|
|5. ||Rewind and play the movie. Click on the game cards.You're now able to flip the cards over one at a time, but you can't flip them back. In fact, you can flip all 16 cards, but then you're stuck, as you can't flip them any longer.What you need to do is to limit the number of cards that can be placed into flippedList to just two. Once flippedList contains a pair of cards, you need to see if those cards are a match. If they are, the cards must be removed from game play. If the two cards aren't a match, they must be flipped back over. In both cases, flippedList needs to be emptied, so it will be ready for the next pair.|
Checking for a Match
Recall that the global variable solveList contains the ordering for the eight texture pairs applied to the cards it gets when assignTextures() is called.You also have the numbers of the cards that are clicked within flippedList. So when two cards have been flipped over, you can use the card numbers within flippedList as indexes into solveList to check which textures have been applied to those cards. To see how this works, examine the following:You can see that cards 9 and 15 were clicked on, and flipped over. But those two cards are using textures 8 and 5, so no match is present. To write this check using Lingo, you can do something like this:
You can shorten this it to one line:
index1 = flippedList
index2 = flippedList
if solveList[index1] = solveList[index2] then
Because you want to do the check once two cards have been flipped over, you can place it within the enterFrame handler. Once transformPercent is greater than 100, the card is completely flipped and you can see if a match has been made. If a match is made, another issue arises: the cards that have been matched need to be removed from game play so they can't be flipped again. The easiest way to implement this is to use another list, matchList. Whenever two cards are flipped that match, they will be added to matchList and removed from play.Let's begin by adding the initial tests to see if flippedList has two cards in it, and also if those two cards are a match.
if solveList[flippedList] = solveList[flippedList] then
|1. ||Right-click the 3D sprite and select Script from the context menu. Add the following conditional tests to the enterFrame handler. Add these lines immediately after the line that sets isRotating to 0:|
So, when transformPercent becomes greater than 100, isRotating is set to 0 and the count of flippedList is checked to see if it is 2. If it is 2, meaning two cards have been flipped over, the cards are checked to see if they match.Now, let's create and initialize matchList so that you can add the matched cards to it. After that you'll add the code that will flip the two unmatched cards back over.
if flippedList.count() = 2 then
if _global.solveList[flippedList] = _global.solveList[flippedList] ¬
|2. ||Add matchList to the property declarations at the top of the script:|
You can add a new property line, or add matchList on the same line as other properties:
Either way is fine. I typically place each property on its own line to allow for easy commenting:
property flippedList, matchList
property flippedList --holds numbers of 2 current cards that are flipped
property matchList --holds numbers of all matched cards
|3. ||Declare matchList to be empty within the beginSprite handler. You can add this line as the last line in the handler:|
matchList = 
|4. ||Replace the -match comment within the enterFrame, with the following:|
When a match happens, the two card numbers are both added to matchList from flippedList. Then flippedList is cleared, ready for two new cards to be added to it.To prevent the matched cards from being flipped again, you need to add a second clause to the if statement that checks flippedList, within the mouseUp handler. In addition to checking the cards in flippedList, you must also now check the matchList as well.
flippedList = 
|5. ||Modify the if statement that checks flippedList, within the mouseUp handler as shown here:Change the if statement from this:|
if not(flippedList.getOne(modNumber)) then
Now when matches are made, they will be added to matchList and, because of this test, they will no longer be able to be flipped back. This effectively removes the cards from game play. However, we still have the matter of what happens when there is no match.
if not(flippedList.getOne(modNumber)) and not(matchList.getOne(modNumber)) ¬
Flipping Two Cards
When two cards are flipped over and they don't match, the cards need to automatically flip back. This will work nearly the same way as one card rotates when clicked, except it won't be initiated by a mouse click. The only difference is you must make two original transforms, and two final transforms to work with.
|1. ||Add the property declaration for these three new properties:|
You only need these three new properties to handle both cards, because you can use whichMod, origTransform, and finalTransform for one of the cards.
property whichMod2, origTransform2, finalTransform2
|2. ||Replace the -no match comment within the enterFrame handler with the following:|
Can you see how this is coming together? If the count of flippedList is 2, a check is done to see if there's a match. If there is no match, isRotating is set to 2 and two model references are created, whichMod and whichMod2. An original transform and a final transform are then created for each of the models. Finally, transformPercent is set to 0.The next step is to add a check for when isRotating is 2 and rotate the two cards when it is.
isRotating = 2
whichMod = wrld.model("c" & string(flippedList))
whichMod2 = wrld.model("c" & string(flippedList))
origTransform = whichMod.transform.duplicate()
finalTransform = whichMod.transform.duplicate()
finalTransform.rotation.y = 180
origTransform2 = whichMod2.transform.duplicate()
finalTransform2 = whichMod2.transform.duplicate()
finalTransform2.rotation.y = 180
transformPercent = 0
|3. ||Add the following conditional test to the very end of the enterFrame handler, after any other end if statements, and just before the end statement:|
When isRotating is 2 this code will rotate both cards at once, back to their initial positions. Once the cards are flipped, isRotating is set to 0 and flippedList is cleared, allowing the two cards to once again be clicked on and flipped.
if isRotating = 2 then
whichMod.transform = origTransform.interpolate(finalTransform, ¬
whichMod2.transform = origTransform2.interpolate(finalTransform2, ¬
transformPercent = transformPercent + 5
if transformPercent > 100 then
isRotating = 0
flippedList = 
|4. ||Close the script window, then rewind and play the movie.Although there are a few things left to take care of, the game is working pretty well at this point. When you click two cards and get a match, the cards remain flipped over and can't be clicked on again. If there is no match, the cards immediately flip back over, ready to be clicked again.|
|5. ||Stop the movie and then save it to your project_four folder.In the next lesson you will add a pause to the game so that the cards wait a bit before flipping back over. You'll also add other finishing touches, such as a timer and a colored background.|