|
Want to thank me for making this book available for free? Just buy Special Edition Using Macromedia Director MX
Advanced Lingo For Games
| |
| Making the Game
Only two behaviors are needed for this game. The main one--the frame behavior--controls the game flow, the questions and answers, the player's score, and the timer. The second behavior is the button behavior, which sends messages to the frame behavior and handles key presses. Frame BehaviorThe frame behavior only needs to know which member holds the question and answer data, and which frame to go to when the last question is over. In addition, you can supply two sounds to be used when the user attempts an answer. Figure 13.2 shows the resulting Parameters dialog box.
Figure 13.2
The frame behavior Parameters dialog box.
property pDataMember -- question text
property pQuestionNum -- current question
property pPossiblePoints -- points to add to score
property pScore -- current score
property pCorrectAnswer -- which is current correct answer
property pCorrectSound, pWrongSound -- sounds
property pEndGameFrame -- frame to go to when game is over
on getPropertyDescriptionList me
list = [:]
addProp list, #pDataMember,[cc]
[#comment: "Data Member",[cc]
#format: #text,[cc]
#default: VOID]
addProp list, #pCorrectSound,[cc]
[#comment: "Correct Sound",[cc]
#format: #string,[cc]
#default: ""]
addProp list, #pWrongSound,[cc]
[#comment: "Wrong Sound",[cc]
#format: #string,[cc]
#default: ""]
addProp list, #pEndGameFrame,[cc]
[#comment: "End Game Frame",[cc]
#format: #marker,[cc]
#default: #next]
return list
end
Notice how you can specify #text as the format for the "pDataMember" parameter. This results in a pop-up menu of text members. You can use other member types as well, such as #bitmap or #sound. If you use #member, a pop-up menu appears that contains all member types. When the frame starts, the question number is set to 1, the score set to 0, and the first question is asked. on beginSprite me pQuestionNum = 1 pScore = 0 showScore(me) askQuestion(me) end The "on askQuestion" handler takes the text from the member specified and extracts the question, answers, and number of the correct answer from it. It populates the question text member{1} as well as the four answer text members{2}.
on askQuestion me
-- get the data
text = pDataMember.text.line[pQuestionNum]
-- reset all the button sprites
sendAllSprites(#makeVisible)
-- get the question, answers and correct answer number
the itemDelimiter = ";"
question = text.item[1]
answers = text.item[2]
pCorrectAnswer = value(text.item[3])
-- display the question
member("Question").text = question{1}
-- display the answers
the itemDelimiter = ","
repeat with i = 1 to 4
member("Answer"&&i).text = answers.item[i]{2}
end repeat
-- start the potential points at 1000
pPossiblePoints = 1000
showPossiblePoints(me)
end
The Lingo property the itemDelimiter specifies the character to be used to separate items in a text string. You can set it to any character, such as a semicolon or comma, and then use the item descriptor to extract segments of a string. The next two handlers are in charge of updating the potential points text member and the score text member.
-- update the possible points display
on showPossiblePoints me
if pPossiblePoints < 0 then pPossiblePoints = 0
member("Possible Points").text = "Points:"&&pPossiblePoints
end
-- update the score display
on showScore me
member("Score").text = "Score:"&&pScore
end
When the user clicks a button, the message is sent back to the frame behavior. The frame behavior determines if the answer is correct.
-- see if an answer is correct
on clickAnswer me, n
if n = pCorrectAnswer then
if pCorrectSound <> "" then puppetSound pCorrectSound
-- add to score
pScore = pScore + pPossiblePoints
showScore(me)
-- move on to next question
nextQuestion(me)
return TRUE
else
if pWrongSound <> "" then puppetSound pWrongSound
-- subtract from potential score
pPossiblePoints = pPossiblePoints - 100
showPossiblePoints(me)
return FALSE
end if
end
When the player gets the right answer, this next handler moves the game on to the next question. If there are no more questions, it moves the game on to the "pEndGameFrame". To determine the number of elements in a string, use the count property. For instance, "myText.word.count" returns the number of words in "myText". You can also use "myText.line.count," "myText.item.count," and "myText.char.count." The latter example is the same as "myText.length."
-- move on to next question
on nextQuestion me
pQuestionNum = pQuestionNum + 1
if pQuestionNum > pDataMember.text.line.count then
-- no more questions
go to frame pEndGameFrame
else
askQuestion(me)
end if
end
The on exitFrame handler needs to decrease points from "pPossiblePoints" in addition to looping on the frame. on exitFrame me -- subtract from potential score pPossiblePoints = pPossiblePoints - 1 showPossiblePoints(me) go to the frame end Because key press messages come to the frame behavior, we need to handle them here. However, the button behaviors will know which button responds to which key. So, we will send the "keyHit" message to all the sprites and let the button behaviors take it from there. -- take any key presses and send to the button sprites on keyDown me sendAllSprites(#keyHit,the key) end Button BehaviorThe button behavior needs only to react to the player's input. This can come from either a mouse click or a key press. This behavior resembles a typical button behavior more than anything else. It records the original member number as the normal state of the button. It assumes that the very next member is the down state of the button. When the user clicks down on the button, the down state is shown. When the user releases the mouse button, the action is taken. If the user moves off the button before releasing the mouse button, then the action is not taken, but instead the button is returned to the normal state. The behavior starts off by gathering two important pieces of information in the on getPropertyDescriptionList handler. The first bit of information is which answer number the button corresponds to. The second is which key on the keyboard the button maps to. Figure 13.3 shows the Parameters dialog box.
Figure 13.3
The button behavior Parameters dialog box.
property pOrigMemNum -- normal member number
property pPressed -- whether the button is being pressed
property pAnswerNum -- which answer the button corresponds to
property pKey -- which key the button is mapped to
on getPropertyDescriptionList me
list = [:]
-- which answer number the button represents
addProp list, #pAnswerNum,[cc]
[#comment: "Answer Number",[cc]
#format: #integer,[cc]
#default: 1]
-- which key the button is mapped to
addProp list, #pKey,[cc]
[#comment: "Key",[cc]
#format: #string,[cc]
#default: ""]
return list
end
The behavior starts by getting the current member number of the sprite to be used as the normal state of the button. The "pPressed" property is used throughout the behavior to tell whether the button is currently being held down by the player. -- remember original, normal, member on beginSprite me pOrigMemNum = sprite(me.spriteNum).memberNum pPressed = FALSE end At the start of a question, the frame behavior asks all the sprites to reset by sending the "makeVisible" message. This resets the buttons to their normal states. This is needed because some buttons may have been removed due to wrong answers by the player. -- respond to frame behavior's message to reset on makeVisible me sprite(me.spriteNum).memberNum = pOrigMemNum end The clicking process starts when the player presses down on the button. The "pPressed" property is set to TRUE and the sprite's member is changed to the down state. -- user clicks down on button on mouseDown me pPressed = TRUE -- change to down state sprite(me.spriteNum).memberNum = pOrigMemNum + 1 end The click process ends if the player lifts up the mouse button while the cursor is over the sprite. If so, the button is returned to the up state{3}, and the answer is sent to the frame behavior to be checked{4}. If the answer is wrong, we remove the button by setting its memberNum to 0.
-- user finished click
on mouseUp me
if pPressed <> TRUE then exit
pPressed = FALSE
-- reset to up state
sprite(me.spriteNum).memberNum = pOrigMemNum{3}
-- check to see if the answer was right
if not sendSprite(0,#clickAnswer,pAnswerNum) then{4}
-- remove the button
sprite(me.spriteNum).memberNum = 0
end if
end
Another way to end a click is to move the mouse off the button before releasing. In this case, we want to give the player the benefit of the doubt and assume that they did not want to click the button in the first place. -- user did not complete click on mouseUpOutside me pPressed = FALSE -- reset button sprite(me.spriteNum).memberNum = pOrigMemNum end When a key on the keyboard is hit, the message is sent to the frame behavior. In turn, our frame behavior sends a "keyHit" message to all the sprites. When one of these button behaviors gets this message, it compares the key that was pressed to the key that the button is supposed to be mapped to{5}. If they match, the button acts just like it has been clicked.
-- respond to the frame behavior's "on keyHit" message
-- if this button is mapped to that key
on keyHit me, key
if key = pKey then{5}
-- check to see if the answer was right
if not sendSprite(0,#clickAnswer,pAnswerNum) then
-- remove the button
sprite(me.spriteNum).memberNum = 0
end if
end if
end
| |