The transform property of a node holds the position, rotation, and scale of that node as a single object.
All objects in a 3D world are built on a base object known as a node. The most basic form of a node is the group object and all objects in a 3D world are built upon the group. These include models, cameras and lights, and because all of these objects are created from this basic object, they all share common functionalityas well as having their own unique functionality specific to the individual objects.
You can get and set the transform for any node in the 3D world. Of particular interest to us is Lingo's interpolate method, which works on transform objects.
You'll use interpolate to animate the cards flipping over as they are clicked on. You'll then use it to animate both cards flipping back if no match was detected.
Before adding the Lingo, let's discuss the concept a little. The interpolate method uses two transformslet's call them original and finaland returns a new transform. The new transform is a copy of the original transform interpolated by some percentage to the final transform. If you interpolate the original transform by 100 percent to the final transform, the two transforms will be equal. In this manner you can move one object to the exact location of another one, or you can rotate something by a desired number of degreesrotating a game card by 180, say.
Let's try a test using the Message window.
Open the Message window and enter the following:
a = transform() b = transform() b.rotation.x = 45 trace(a.rotation) -- vector( 0.0000, 0.0000, 0.0000 ) trace(b.rotation) -- vector( 45.0000, 0.0000, 0.0000 ) newTran = a.interpolate(b, 50) trace(newTran.rotation) -- vector( 22.5000, 0.0000, 0.0000 )
As you can see, by interpolating transform a by 50 percent to transform b, the rotation on the X-axis becomes 22.5 degrees (50 percent of 45 degrees). You can take this a step further and create animation by interpolating from 0 to 100 and repeatedly setting the transform of the object to the new, interpolated transform.
Right-click the 3D sprite and select Script from the context menu. Within the mouseUp handler, replace the TRace(modNumber) command with the following:
isRotating = 1 whichMod = clickMod origTransform = clickMod.transform.duplicate() finalTransform = clickMod.transform.duplicate() finalTransform.rotation.y = 180 transformPercent = 0
First, isRotating is set to 1. You will use this within the enterFrame handler as a means of knowing that a card is rotating. The whichMod variable is used to store a reference to the clicked model. The next two lines create duplicates of the model's transform and store it in origTransform and finalTransform. The finalTransform rotation on the Y-axis is then set to 180 degrees. Finally, the transformPercent is set to 0.
You're now ready to code the enterFrame handler that will use the variables you just initialized. But first you must declare these properties so they aren't just local to the mouseUp handler.
Add the following property declarations at the top of the script:
property isRotating, whichMod, transformPercent property origTransform, finalTransform
With the variables declared as properties, you can use them within other handlers and methods in the script.
Create the enterFrame handler, as shown here:
on enterFrame me if isRotating = 1 then whichMod.transform = origTransform.interpolate(finalTransform, ¬ transformPercent) transformPercent = transformPercent + 5 if transformPercent > 100 then isRotating = 0 end if end if end
Can you see how this works now? When a game card is clicked on, isRotating is set to 1 and a reference to its model is stored in whichMod. Two transforms are then created and set to duplicates of the game card's transform. The rotation of finalTransform is then set to 180 degrees on the Y-axis:
Now, once isRotating has been set to true by clicking on a card, the if statement within the enterFrame will execute.
The very first line uses the interpolate method to create a new transform that is a copy of the original interpolated by a percentage (transformPercent) toward the final transform. The card's transform property is then set to the new transform.
Next, the transformPercent is incremented by 5 and tested to see if it's greater than 100. As the enterFrame handler runs and TRansformPercent is incremented, the card animates towards the final transform. The following image shows the card at various percentages of the final rotation:
Once transformPercent is greater than 100 (105, actually), isRotating is set to 0. This of course causes the code that rotates the model to stop executing. And, because it is fully flipped over, that's exactly what we want to happen.
Name the script game script, then rewind and play the movie. Click on the cards. This happens because when you click on the game board, the only check being done is to determine whether or not a card was clicked. The problem lies in this code within the mouseUp handler:
As you click the cards, they flip over in a nice, smooth fashion. As you can see, Lingo's interpolate method works quite well for getting the card rotated into just the right position. If you click fast on the cards, however, you will notice a problem:
if not(voidP(clickMod)) then modName = clickMod.name if modName.char = "c" then delete modName.char modNumber = value(modName)
As long as a model is clicked, and that model's name starts with "c", whichMod is set to the model. Once that happens, the code within the enterFrame handler rotates the new model.
To fix this, you need to add a check that only allows a card to be rotated if another card isn't already rotating. Because isRotating is set to 1 when a card is rotating, and to 0 when the card is finished, you can use it to test against.
Within the mouseUp handler, add the following if statement and matching end if. Add the if statement immediately before the first if statement already in place, making it the very first test in the handler:
if not(isRotating) then
Now, you can also add the matching end if. It should be placed immediately before the handler's end statement.
This test insures that the code within the mouseUp handler that sets whichMod to the clicked model and sets up the transforms, will only execute when isRotating is false, or 0.
For reference, the mouseUp handler should now look like this:
on mouseUp me myPoint = _mouse.mouseLoc - point(sp.left, sp.top) clickMod = sp.camera.modelUnderLoc(myPoint) if not(isRotating) then if not(voidP(clickMod)) then modName = clickMod.name if modName.char = "c" then delete modName.char modNumber = value(modName) isRotating = 1 whichMod = clickMod origTransform = clickMod.transform.duplicate() finalTransform = clickMod.transform.duplicate() finalTransform.rotation.y = 180 transformPercent = 0 end if end if end if end
Rewind and play the movie. Try clicking another card while one is rotating.
Now you can no longer start a card rotating while another is already doing so. But you can click the same card twice, flipping it over, then back again. This is no good, because the rules of the game say you must flip two different cards at a time. A check is needed that will prevent a card from being clicked on once it's been flipped.
Stop the movie before continuing.