Memory
August 24, 1998
by Pat McClellan
Dear Multimedia Handyman,
I'm trying to create a memogame -- like the old Concentration game show -- with three columns and four lines. Everytime you click on a square, an image appears, if you click on another, if it's the same one, both will stay, otherwise they'll disappear. The game is won when all pairs are matched. So I guess I should use variables, but as I'm a beginner I'm really stuck with the lingo...
I would appreciate your help.
Thanx
Tonard
Dear Tonard,
There are a lot of variations on this game. I'm going to stick to your specifications in creating some Lingo that you can apply to all the sprites in a matching game. You could do what you describe with global variables, but I much prefer the behavior approach. It's much more reusable. The only global I'm going to use is gSpritesMatched, which will keep track of how many sprites have disappeared. This will tell us when the game is over.
In a movie script, let's set up a resetGame
handler and an on idle
handler to monitor whether the game has been won.
on startMovie resetGame end on resetGame global gSpritesMatched set gSpritesMatched = 0 sendAllSprites (#reset) end on idle global gSpritesMatched if gSpritesMatched = 12 then alert "You win!" resetGame end if end
Note that in the resetGame handler, I used a sendAllSprites()
command. This is a very useful way to send a message to the behavior scripts attached to all sprites. In this case, all sprites will get the message to execute their reset
handler (if they have that handler). In fact, as you'll see below, I'm going to use the sendAllSprites()
command in the behavior itself to send messages to the other sprites. If you've never used sendAllSprites()
, I suggest you check it out in the Lingo dictionary. Also read up on the sendSprite()
command, which we'll also be using.
OK, now we need to figure out what properties the behavior is going to need. First, when we drag it onto the sprite, we need to be able to specify which cast member will be the "front" or unique member. All of the "backs" in my example are the same cast member, though this is not needed. I've set up this behavior so that you put the "backs" in the score, rather than the "fronts". We'll also need to give each sprite an ID, so that this ID can be compared with the ID of the other selected card. So, we'll start with properties called pFront and pMyID. I'm going to store the original cast member of the sprite in pBack.
We'll also want to keep track of whether the sprite is selected (flipped over) or not. For this, I'll use a simple flag property called pSelected, which will be set to FALSE or TRUE.
In order to make the card "disappear", I'm simply going to set the locH of the sprite to a number which is offstage. However, when we reset the game, we'll want the sprite to return to its original locH, so we'll need to capture this information and store it in a property called pLocH.
Finally, I like to use pMySpriteNum instead of writing out sprite the spriteNum of me
everytime.
Now that we've got all our properties, let's figure out all the handlers we'll need. The on getPropertyDescriptionList
handler will let the author specify pFront and pMyID. We'll set the other properties in the on beginSprite me
handler.
We'll need a mouseUp (or mouseDown) handler to set the pSelected to TRUE, swap in the pFront member, and send out the message to check for a match. If a match is found, we'll need a makeMatch handler to move the sprites offstage and increment gPairsMatched. And if a match is not made, then we'll want a handler to flip the sprites back to pBack. Finally, we'll need a reset handler to set the sprite back to its original locH and cast member.
I think that's everything, so let's give it a crack, Nigel!
-- MatchGame behavior -- Used to set up pairs of matching sprites property pFront -- the "front" of the card property pBack -- the "back" of the card property pMyID -- matching pairs will have the same ID property pSelected -- state of the card, selected/not property pLocH property pMySpriteNum global gSpritesMatched on getPropertyDescriptionList set pmySpriteNum = the currentSpriteNum if pMySpriteNum = 0 then set memdefault = 0 else set memref = the member of sprite pMySpriteNum set castlibnum = the castlibnum of memref set memDefault = member (the membernum of ¬ member memref + 1) of castlib castlibnum end if set p_list = [#pMyID: [ #comment:"ID:",#format:¬ #symbol,#default: #item1 ], #pFront:[ #comment:¬ "Member:",#format: #graphic,#default: memDefault]] return p_list end on beginSprite me set pMySpriteNum = the spriteNum of me -- put "Sprite" && pMySpriteNum && "is" &&¬ pMyID && pFront set pSelected = FALSE set pBack = the member of sprite pMySpriteNum set pLocH = the locH of sprite pMySpriteNum end on mouseUp me set pSelected = TRUE set the member of sprite pMySpriteNum to pFront updateStage sendAllSprites(#checkMatch, pMyID, pMySpriteNum) end on checkMatch me, testID, testSpriteNum if pSelected = TRUE AND testSpriteNum <> ¬ pMySpriteNum then if testID = pMyID then beep startTimer repeat while the timer < 60 -- delay end repeat makeMatch me sendSprite(testSpriteNum, #makeMatch) else beep startTimer repeat while the timer < 60 -- delay end repeat flipBack me sendSprite(testSpriteNum, #flipBack) end if end if end on makeMatch me -- do whatever you want set the locH of sprite pMySpriteNum to 800 set pSelected = FALSE set gSpritesMatched = gSpritesMatched + 1 end on flipBack me -- play annoying sfx if desired set the member of sprite pMySpriteNum to pBack set pSelected = FALSE end on reset me set the member of sprite pMySpriteNum to pBack set the locH of sprite pMySpriteNum to pLocH end
Let's take a look at the way this behavior sends and receives messages from the other sprites' behaviors. In the mouseUp handler, a message is sent to all other sprites to execute their checkMatch handler. We go on to specify the ID and spriteNum of the sprite that is sending the message.
This message is received by all sprites -- including the sprite that sent the message. This is important, because the sprite that sent the message will ALWAYS have a matching ID, so we have to screen this sprite out by checking the spriteNum. Let's walk through an example. You click on sprite A. A sends out a message to sprites A through L -- remember, only A has been selected. In sprites A through L, the first line of the checkMatch handler runs an if statement that checks on 2 things. First, if the receiving sprite is NOT already selected, nothing else happens. So, that means that sprites B - L immediately exit the handler while sprite A proceeds. The second condition of the if statement checks to see if the spriteNum of the sending sprite is the same as the receiving sprite. In our case, A sent the message and A is also the receiving sprite, so A now exits and nothing else happens.
Now you select the second sprite in your pair, let's say D for example, and let's assume that it is not the correct match. D now sends out the message to A through L to checkMatch. Only A and D will make it past the first condition of the if statement, because they're the only ones with pSelected set to TRUE. Now, A and D will compare their own spriteNum to the spriteNum of the sending sprite. Since D matches, it will exit the handler and only A will continue. Now, sprite A will compare its pMyID to the sending sprite's pMyID. Since it doesn't match, A will delay for a moment (so the user can contemplate their mistake), then issue the flipBack command to itself. It also sends the flipBack message to the other selected sprite.
If the two selected sprites have matching IDs, the checkMatch handler will beep, pause a second, then send the makeMatch command to itself and the other selected sprite.
We can use the sendSprite command in the checkMatch handler (instead of the sendAllSprites) because we happen to know exactly which sprite to send the message to. That information was sent out as pMySpriteNum... and received as testSpriteNum.
This behavior serves as a great example of how powerful inter-sprite communications can be. I hope you can apply these principles in many other applications.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.