Starting the Game


The functions that we cover next are built with the framework of the game in a circular fashion: All the functions are used within one game cycle and again within the next game cycle. This kind of flow is specific to games and you must keep it in mind when writing code. In particular, game states need to be reset properly at the beginning of a new cycle.

At the beginning of each round, some of our assets need to be edited and some variables initialized. The newRound() function, defined in the GameModel class, takes care of establishing initial settings for each round in the game:

 public function newRound() {    roundNumber++;    hangManStates = [                 {id: "head", active: false},                 {id: "body", active: false},                 {id: "leftArm", active: false},                 {id: "rightArm", active: false},                 {id: "leftLeg", active: false},                 {id: "rightLeg", active: false}                 ];    var aAvail:Array = new Array();    for(var i:Number = 0; i < wordList.length; i++){       var oItem:Object = wordList[i];       if(oItem.active) aAvail.push(i);    }    var nIdx:Number = Math.floor(Math.random() * aAvail.length);    selectedIndex = aAvail[nIdx];    wordList[selectedIndex].active = false;    createChoices();    createDisplayedWord();    gameState = "newround";    gameStatus = "beginPlay"; } 

newRound() also prepares the states of the hangman character. The hangManStates property is an array created to store the state of each body part. Since the model is simply tracking states of the game, the model doesn't need to know which MovieClip objects are actually representing those body parts — that job is the responsibility of the GameView class. If you look at the hangManStates getter/setter property of the GameModel, you can see that an event is dispatched every time new values are set:

 public function set hangManStates(aStates:Array):Void {      _states = aStates;      dispatchEvent({type: "hangManUpdate", target: this}); } 

Whenever the "hangManUpdate" event is dispatched from the GameModel, the onHangManUpdate() function is invoked within the GameView class:

 private function onHangManUpdate(oEvent:Object):Void {    trace("GameView.onHangManUpdate >");    var m:GameModel = oEvent.target;    var aStates:Array = m.hangManStates;    var nCount:Number = aStates.length;    for (var i = 0; i < nCount; i++) {       var oState:Object = aStates[i];       var mc:MovieClip = matchStateToClip(oState.id);       mc._visible = oState.active;       mc.gotoAndStop(m.roundNumber);    } } 

Here, a for() loop cycles through the states stored within the hangManStates property of GameModel. The matchStateToClip() function within the GameView class matches the id value shown earlier in the newRound() function of the GameModel class to each MovieClip object responsible for displaying that body part. Each body part also jumps to the frame number corresponding to the GameModel's roundNumber to display a new color scheme.

The hangManStates property is set in two places within the GameModel class: the newRound() function (as we've previously discussed) and the lookForMatch() function. This function sequentially sets the active flag within each object of the hangManStates array. Initially, at the start of each round, all of the hangman's body parts have their active property set to false. However, if the lookForMatch() function determines that a selected letter is not found within the challenge phrase, the active property of the "next in line" object within the hangManStates array is set to true. The hangManStates property is then reset to itself, forcing a "hangManUpdate" broadcast. As such, the onHangManUpdate() function within the GameView class is called again, setting the visibility of the "next in line" hangman body part to true.

Display the Letters of the Alphabet

The newRound() function of the GameModel also sets the gameState property to a value of "newround", which is broadcasted to any listener of this event. The GameController class listens for these changes, and invokes its positionAlphabet() function.

This function moves the vertical position of the GameLetter components displaying the clickable letters of the GameController class. This function also sets the text color of each GameLetter instance to black. (Whenever a GameLetter instance is clicked, the text color of the instance is set to gray in the onLetterPicked() function of the GameView class.)

 private function positionAlphabet():Void {    for (var i in mcAlphabet) {       if(mcAlphabet[i] instanceof MovieClip){          var cgl:GameLetter = mcAlphabet[i];          cgl._y = 0;          cgl.letterColor = 0x000000;       }    } } 

Choose a Random Word

The selection of words (or challenge phrases) is stored in an array called wordList, which is defined at the beginning of the game in the GameModel class. In the newRound() function, a challenge phrase is randomly picked from the wordList array:

 var aAvail:Array = new Array(); for(var i:Number = 0; i < wordList.length; i++){    var oItem:Object = wordList[i];    if(oItem.active) aAvail.push(i); } var nIdx:Number = Math.floor(Math.random() * aAvail.length); selectedIndex = aAvail[nIdx]; wordList[selectedIndex].active = false; 

The aAvail array is used to store any challenge phrase that has yet to be played in the game. The for() loop cycles through each object stored in the wordList property, and checks its active property. If it hasn't been played (that is, its active value is true), then the object is added to the aAvail array. Once the available challenge phrases have been gathered, a random index number is selected for the aAvail array. This value is then used to set the selectedIndex property of the GameModel class. The selectedIndex property is used to determine which word is active during the round. In the last line of the previous code block, the active property for that word is set to false so that it can't be picked again in future rounds.

Note 

In this version of the game, a word is randomly selected from a pool for each round. As such, the difficulty of each word (number of characters, number of words, and so on) is not ranked. You can modify the game to create a series of word arrays, each one varying in level of difficulty. As the player progresses to the next round, a word from another array can be chosen.

Create the Letters of the Displayed Word

The createDisplayedWord() function, invoked from the newRound() function of the GameModel class we mentioned in the previous section, builds the current state of the displayed word to the game player.

At the beginning of the createDisplayedWord() function, we create a String variable named sWord to hold the individual letters of the displayed word (or challenge phrase). Because the newRound() function already set a new selectedIndex value, the selectedItem.label value will be set to the new challenge phrase. In this for() loop, the sWord variable is built into a series of question marks ("?") or empty spaces (" "). So, if the challenge phrase (that is, selectedItem.label) was set to "Lost," the sWord variable would equal "????". Or, if the challenge phrase was "The Comeback", the sWord variable would equal "??? ????????". After the sWord string has been generated, the displayedWord property of the GameModel is set to the value of sWord.

 private function createDisplayedWord():Void {    var sWord:String = " ";    var nCount:Number = selectedItem.label.length;    for(var i:Number = 0; i < nCount; i++){       sWord += (selectedItem.label.substr(i, 1) != " ") ? "?" : " ";    }    displayedWord = sWord; } 

Because the displayedWord property's setter function dispatches the event "wordUpdate", the GameView class's displayWord() function will be invoked, fetching the new displayedWord property from the GameModel class:

 private function displayWord():Void {    trace("GameView.displayWord>");    if(mcWord instanceof MovieClip) mcWord.removeMovieClip();    mcWord = createEmptyMovieClip("mcWord", getNextHighestDepth());    with(mcWord){       _x = 35;       _y = 25;    }    var sWord:String = model.displayedWord;    var nX:Number = 0;    var nY:Number = 0;    for (var i:Number = 0; i < sWord.length; i++) {       var sChr:String = sWord.substr(i, 1);       if (sWord.substr(i, 1) == " ") {          nX = 0;          nY += 30;          continue;       }       var t:TextField = mcWord.createTextField("t_" + i,image from book          mcWord.getNextHighestDepth(), nX, nY, 25, 25);       with (t) {          border = true;          embedFonts = true;          background = true;          antiAntiAliasType = "advanced";          gridFitType = "subpixel";          backgroundColor = (sChr == "?") ? 0x99CCFF : 0x9999FF;          text = sChr;       }       t.setTextFormat(tfCentered);       nX += 25;    } } 

The displayWord() function completes one primary task: to generate a series of TextField instances displaying each of the characters in the displayedWord value of the GameModel class. An empty MovieClip object named mcWord is created, and a for() loop cycles over each character of the displayedWord value (represented as the local variable, sWord). In each for() loop cycle, a TextField instance is created to display an individual character. If an empty space (" ") is found in the sWord variable, then the Y position of the subsequent TextField instance is shifted down 30 pixels. This procedure places each word in a multiword challenge phrase on its own line. You can see this effect in Figure 31-4, where the second line of the mcWord instance is below the first line.

Cross-Reference 

The TextField instances of this function use the new Flash Player 8 FlashType rendering engine. Because the tfCentered instance (a TextFormat instance) uses center alignment, the gridFitType property of the TextField instance is set to "subpixel", to render the text more sharply. For more information about FlashType, read Chapter 30, "Applying HTML and Text Field Formatting."




Macromedia Flash 8 Bible
Macromedia Flash8 Bible
ISBN: 0471746762
EAN: 2147483647
Year: 2006
Pages: 395

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net