Note About This Book: Advanced Lingo For Games was written by Gary Rosenzweig in 2000 for users of Macromedia Director 7. It is presented here for free on an as-is basis, with no updating. Most of the information and code here can be used in the most recent version of Director. The book has been reproduced from the final editing files archived in 2000, and not the final proof galleys. So some minor differences between this version and the printed version my exist. The entire contents of this book are Copyright 2000, Gary Rosenzweig. No part may be reproduced or copied without written permission. The text here is provided for individual use only.
Want to thank me for making this book available for free? Just buy Special Edition Using Macromedia Director MX and we'll call it even!

Advanced Lingo For Games
by Gary Rosenzweig


Chapter 15 Section 3

Making the Game

Although there is a small behavior attached to the text sprite that contains the letters of the alphabet, the main script for this game is the frame behavior. This frame behavior is in charge of handling all aspects of the game except the keyboard interaction.

The Frame Behavior

There are many similarities between this frame behavior and the one for the cryptogram game. Our property declarations and on getPropertyDescriptionList reflect this, as we see many of the same properties show up.

We will have a "pPhraseSource" property that is a name of a text member. This member contains the list of phrases to be used in the game. The "pPhraseOrder" property works in the same way as in the previous chapter too. The game can use the phrases sequentially, or in a random order.

In addition to these properties, there needs to be one that identifies the sprite channel location of the hangman graphic. There are also four sound properties to be used in various parts of the game. Figure 15.3 shows the Parameters dialog box for this behavior.

Figure 15.3
The Parameters dialog box for the frame behavior is shown here.

property pPhraseList -- list of phrases taken from text member
property pPhrase -- the phase to be guessed
property pWorkspace -- the solution as it is being built
property pLetters -- the letters the player has used
property pHangmanNum -- progress of the hangman drawing
property pGameInProgress -- whether the player can make a guess

property pPhraseSource
property pPhraseOrder
property pHangmanSprite
property pRightLetterSound, pWrongLetterSound
property pLiveSound, pDieSound
property pEndFrame

on getPropertyDescriptionList me
  list = [:]
  
  -- the text member with the phrases in it
  addProp list, #pPhraseSource,[cc]
    [#comment: "Phrase Source",[cc]
     #format: #text,[cc]
     #default: VOID]
  
  -- what order to present the phrases
  addProp list, #pPhraseOrder,[cc]
    [#comment: "Phrase Order",[cc]
     #format: #string,[cc]
     #range: ["In Order", "Random"],[cc]
     #default: 3]
  
  -- where the hangman graphic is
  addProp list, #pHangmanSprite,[cc]
    [#comment: "Hangman Sprite",[cc]
     #format: #integer,[cc]
     #default: 5]
  
  -- sounds
  addProp list, #pRightLetterSound,[cc]
    [#comment: "Right Letter Sound",[cc]
     #format: #string,[cc]
     #default: ""]
  addProp list, #pWrongLetterSound,[cc]
    [#comment: "Wrong Letter Sound",[cc]
     #format: #string,[cc]
     #default: ""]
  addProp list, #pLiveSound,[cc]
    [#comment: "Game Over - Live Sound",[cc]
     #format: #string,[cc]
     #default: ""]
  addProp list, #pDieSound,[cc]
    [#comment: "Game Over - Die Sound",[cc]
     #format: #string,[cc]
     #default: ""]
  
  -- the frame to go to when the last phrase is solved
  addProp list, #pEndFrame,[cc]
    [#comment: "End Game Frame",[cc]
     #format: #marker,[cc]
     #default: #next]
  
  return list
end

The behavior begins by getting the phrases out of the text member, and then setting up the first phrase in the list. It converts the entire phrase to uppercase, even if it isn't in uppercase while stored in the text member.


-- get phrases, set up the first phrase
on beginSprite me
  getPhrases(me)
  setUpPhrase(me)
end

-- read phrases from text and put into list
on getPhrases me
  pPhraseList = []
  text = member(pPhraseSource).text
  
  -- make phrases all capital letters
  repeat with i = 1 to text.length
    put convertToCaps(me,text.char[i]) into char i of text
  end repeat
  
  -- add each to list
  repeat with i = 1 to text.line.count
    if text.line[i].length = 0 then next repeat -- skip empty lines
    add pPhraseList, text.line[i]
  end repeat
end

To set up a phrase, the following handler first picks one from the list. If "pPhraseOrder" is "In Order", then it picks the next one in the list{1}. Otherwise, it picks a random phrase{2}. Either way, the phrase is removed from the list so that it isn't picked again.

Next, the "pWorkspace" property is built by calling our "on showWorkspace" handler. At the beginning of the game, this string contains the phrase, but with all underscore characters in the place of the letters. This string is presented in a text sprite, as well as a string of all the letters of the alphabet. The latter is built by calling "on showLetters".

In addition to these two text sprites, the message text is also cleared, and the hangman is drawn. Because this segment of the game is just beginning, the "pHangmanNum" is set to 0, and when the hangman is drawn, it's the first hangman graphic that is used, called "Hangman 0".

One thing that the "on setUpPhrase" handler does before anything else is check to make sure that there is a phrase left in the list. Because we will be calling this handler every time the user is done with one phrase and wants to move on to the next, this is the best place to check for this end-of-game condition.


-- set up a phrase
on setUpPhrase me
  -- make sure there are phrases left
  if pPhraseList.count < 1 then
    -- if not, advance the movie
    go to frame pEndFrame
    exit
  end if
  
  -- get next phrase in list
  if pPhraseOrder = "In Order" then
    pPhrase = pPhraseList[1]{1}
    deleteAt pPhraseList, 1 -- remove phrase
    
    -- pick a random phrase from list
  else if pPhraseOrder = "Random" then
    r = random(pPhraseList.count)
    pPhrase = pPhraseList[r]{2}
    deleteAt pPhraseList, r -- remove phrase
  end if  
  
  -- clear workspace, letters and hangman
  pWorkspace = ""  
  pLetters = []
  pHangmanNum = 0
  
  -- allow user to guess
  pGameInProgress = TRUE
  
  -- clear all screen displays
  member("message").text = ""
  showLetters(me)
  showWorkspace(me)
  showHangman(me)
end

The "on showWorkspace" handler creates a string from scratch. The handler loops through each letter of the phrase and determines if the letter is contained in "pLetters"{3}. If so, the letter is added to the string{4}. If not, an underscore character is added{5}. The result is placed in the "workspace" text member.


-- show the phrase in its current state of being solved
on showWorkspace me
  -- recreate workspace each time
  pWorkspace = ""
  
  -- build workspace one character at a time
  repeat with i = 1 to pPhrase.length
    realChar = pPhrase.char[i] -- get correct character
    
    -- see if it is a letter
    ascii = chartonum(realChar)
    if ascii < 65 or ascii > 90 then
      put realChar after pWorkspace -- place non-letter
      
    else if getOne(pLetters,realChar) then{3}
      put realChar after pWorkspace -- place letter{4}
      
    else -- it is a letter, but not one guessed yet
      put "_" after pWorkspace -- put placeholder{5}
    end if
  end repeat
  
  -- display the workspace
  member("workspace").text = pWorkspace
end

The "on showLetters" handler works in a similar way. It loops through all the letters of the alphabet using ASCII values. If the letter is in "pLetters", then it has been chosen, and a space is placed in the string. Otherwise, the letter is placed in the string. The result is a string that contains only letters that have not yet been chosen. This is placed in the "letters" text member.


-- show the letters that the user has not yet chosen
on showLetters me
  -- start with empty string and build list
  letterText = ""
  
  -- loop through letters according to ASCII values
  repeat with i = 65 to 90
    letter = numtochar(i)
    
    -- place space if letter has been used
    if getOne(pLetters,letter) then
      put SPACE after letterText
      
    else -- place actual letter if it has not yet been used
      put letter after letterText
    end if
  end repeat
  
  -- display letters
  member("letters").text = letterText
end

The "on showHangman" handler draws the hangman graphic on the screen. It takes the property "pHangmanNum" and determines which graphic to place in the sprite channel. If the handler figures out that the graphic is the last one in the sequence, it ends this portion of the game.


-- draw hangman graphic according to state of game
on showHangman me
  -- show a numbered bitmap
  sprite(pHangmanSprite).member = member("Hangman"&&pHangmanNum)
  
  -- if this is the last bitmap in the series, the game has been lost
  if the number of member ("Hangman"&&(pHangmanNum+1)) < 1 then
    if pDieSound <> "" then puppetSound pDieSound
    member("message").text = "Game Over. Try Another."
    pGameInProgress = FALSE -- do not allow more guessing
  end if
end

This next handler is identical to the "on convertToCaps" handler used in the previous chapter.


-- utility handler that takes a character and converts it to uppercase
on convertToCaps me, c
  ascii = chartonum