Puzzle Project: Game Logic Using Object-Oriented Scripting

| ACG home | SaneDraw home | Instructor home | learning resources home | class home | handouts index |

Outline of the steps in the second phase of the project

After completing the layout of the graphic elements in the previous session, we need to add the scripts that allow the player to interact with the game pieces.

  1. Find and re-open the Director movie with your puzzle.

  2. Add a cast member for the "missing" gamepiece using the shape tools.

  3. Make the registration point of the bitmap cast members the same as for the shape member.

  4. Make the elements of the game respond to user clicks.

  5. Provide visual feedback to the user when a click on a game piece occurs.

  6. Create a movie script with a handler that initializes the objects used during the game.

  7. Create a parent script for the squares of the gameboard.

  8. Add to the frame script already created in the previous session, so that user clicks will be intercepted.

  9. Create another movie script for the handlers which need to execute while the game is in progress.

  10. Run and test the movie. When done, make sure to save your work for refinements in the next session.


If you have the Shockwave plugin properly installed in your browser, you can see a working example of this second version of the puzzle. You can also download an editable copy of the sample Director movie (Director 5 for Macintosh format, Stuffed and BinHexed, 14,871 bytes).

Step-by-step instructions for the 2nd phase of the project


Re-open your movie

After the movie is up on the screen, you may need to again position and size the stage:

  1. File-->Preferences-->General, uncheck "Centered".

  2. Modify-->Movie-->Properties, enter 240 x 240 for the size, 0 and 20 for the location.

| return to outline |


Create a shape cast member

For the scripts to work, it is important that all cast members used for gameboard squares appear in consecutive positions of the Internal Cast, as well as consecutive channels of frame 1 of the Score, and that this new shape member be the last one.

  1. Display the Cast window, if necessary, using the Window menu.

  2. Select position 16 in the Cast (the first one after the bitmaps with the game pieces).

  3. Display the Tool Palette, if necessary, using the Window menu. the tool palette

  4. Select the unfilled Rectangle tool and use it to draw a box directly on the Stage, in the lower-right location of the gameboard, and the same size as the game piece bitmaps.
    the rectangle tool draw box shape on the stage

  5. Make sure that the new sprite appears in the first available channel of the first frame of the Score, after the bitmaps you laid out in the previous session.
    the box sprite in the score

  6. Use the Tool Palette controls to change the line settings of the box to "No Line" to make the box completely invisible.
    select no line in toolbox

  7. Use the Modify-->Sprite-->Properties dialog to enter the location and size of the new sprite, so it fits in exactly with the grid of squares on the gameboard.
    sprite properties dialog

  8. Since the box is invisible, its thumbnail in the Cast window is blank. To make the cast member more recognizable, you might want to enter a descriptive name for it, in the name field at the top of the Cast window.
    naming the box shape cast member

| return to outline |


Adjust registration point of bitmap cast members

The registration point of bitmap cast members must be set individually. You will need to repeat the following steps for each one of the 15 game piece bitmaps:

  1. Double-click the thumbnail of the game piece in the cast window, to open the bitmap in the paint window.

  2. Select the registration point tool in the paint window's toolbox. The current registration point will be diaplayed as the intersection of two dotted lines.
    the registration point tool

  3. Click on the first pixel at the upper-left corner of the game piece. For greater accuracy you may want to zoom in first (in the View menu).
    set registration point of bitmap cast member

  4. To go on to the next bitmap, double click on its thumbnail in the cast window, or click the "Next Cast Member" button in the paint window.
    next cast member button

| return to outline |


Mark game sprites as editable

Display the score window (use the Window menu if necessary), then select all the sprites representing gameboard squares:

  1. Click and drag through the frame 1 cells that represent elements of the game (background, squares, "missing piece"), so that they are all selected.

  2. Click on the "Editable" checkbox to mark it with an X.

  3. Turn off the "Moveable" checkbox (this is no longer needed, since the gamepieces will move under script control).
    mark sprites as editable in score

| return to outline |


Mark game piece cast members to highlight when clicked

As for the registration point, the highlighting of bitmap cast members must be set individually. You will need to repeat the following steps for each one of the 15 game piece bitmaps (the "missing piece" should obviously not highlight):

  1. Display the cast window (use the Window menu if necessary)

  2. Click on the thumbnail of the cast member to select it

  3. Click on the Information ('i' in a circle) button at the top of the Cast window, or use Modify-->Cast Member-->Properties.

  4. Click on the "Highlight When Clicked" checkbox to mark it with an X.
    turn on highlight property of cast member

| return to outline |


Enter initialization movie script

Movie Scripts appear as members in the cast window, just like the frame script entered in the previous session of the project.

  1. If the script window is already open, click on its "plus" button to create a new script, otherwise display the script window using the Window menu (this should imediately create a blank new script cast member). In both cases, you should end up with an empty window--check that the title bar does say it's a movie script.
    empty script window
  2. To enter the scripts for this project, you can directly copy text from the Web browser window and paste it into the script window. If you prefer to type in the program from scratch, take advantage of the "Alphabetical Lingo" button to enter statement templates--this saves time and minimizes misspellings.
    Alphabetical Lingo button in script window
    The completed script should read as follows:
    ---------- Puzzle 02 -- phase 2 of the Puzzle project ------------
    --------- Copyright 1996 by Sandro Corsi (corsi@ibm.net) ---------
    --The scripts in this movie assume that the cast members with the 
    --images of the gamepieces are arranged sequentially at the 
    --beginning of the internal cast. The cast member for the missing 
    --piece (an unfilled, unstroked box shape) is the last gamepiece
    --cast member.
    --It is also assumed that the gamepiece sprites are arranged
    --sequentially in the score, after any mumber of sprites used
    --to create the background of the gameboard. The sprite for the
    --missing piece comes right after the gamepiece sprites.
    ------------------------------------------------------------------
    on startMovie
      --------------- declare global variables ---------------
      -- game size specifications
      global gNumberOfSquares, gSquaresPerRow
      -- Squares (= available positions for gamepieces)
      global gSquareList, gSquareChannelStart, gHoleColumn, gHoleRow
      
      --------------- initialize global variables ---------------
      put 16 into gNumberOfSquares -- total available Squares
      put 4 into gSquaresPerRow -- how many Squares wide is each row
      put [] into gSquareList -- list of child objects representing Squares
      put 2 into gSquareChannelStart -- first channel containing Square sprite
      -- initialize missing gamepiece position to be the last Square
      put (gNumberOfSquares-1) mod gSquaresPerRow+1 into gHoleColumn
      put (gNumberOfSquares-1)/gSquaresPerRow+1 into gHoleRow
      
      --------------- create Square objects ---------------
      repeat with SquarePosition = 1 to gNumberOfSquares
        append gSquareList, new(script "SquareParentScript", SquarePosition)
      end repeat
      updateStage -- force redraw
    end
    
  3. Verify that the syntax is correct by watching the type alignment after pressing the TAB key.
  4. In the text above, the lines beginning with two (or more) hyphens are comments. They are very important in that they clarify the meaning of the script, but for the purpose of this project they can be omitted.

| return to outline |


Enter parent script for squares

Parent scripts must be entered as movie scripts. They must be named with the exact same name used in the statement that creates the objects:

  1. Click on the "plus" button of the script window  to create a blank new movie script. Check again that the title bar reports this as a movie script.

  2. Click to place the insertion point in the cast member name field (at the top-center of the script window) and type the name SquareParentScript

  3. Place the insertion point back in the body of the window, and enter the following script:

    property pSpriteOfSquare, pColumnOfSquare, pRowOfSquare
    on new me, position
      global gSquareChannelStart, gSquaresPerRow
      set pSpriteOfSquare to position-1+gSquareChannelStart
      set the puppet of sprite pSpriteOfSquare to TRUE
      set the memberNum of sprite pSpriteOfSquare to position
      put (position-1) mod gSquaresPerRow+1 into pColumnOfSquare
      put (position-1)/gSquaresPerRow+1 into pRowOfSquare
      return me
    end
    on click me
      if pieceCanMove(me) then
        beep
        movePiece me
      else
        beep 2 -- not a smart move
      end if
    end
    on pieceCanMove me -- is Square just left, right, above, or below hole?
      global gHoleColumn, gHoleRow
      if pColumnOfSquare = gHoleColumn then
        if pRowOfSquare = gHoleRow-1 then return TRUE --just above hole
        if pRowOfSquare = gHoleRow+1 then return TRUE --just below hole
      end if -- same column
      if pRowOfSquare = gHoleRow then
        if pColumnOfSquare = gHoleColumn-1 then return TRUE --just left of hole
        if pColumnOfSquare = gHoleColumn+1 then return TRUE --just right of hole
      end if -- same row
      return FALSE
    end
    on movePiece me -- trade places with hole
      global gHoleColumn, gHoleRow, gSquaresPerRow, gNumberOfSquares
      -- assign my current cast member to sprite at former hole location
      put (gHoleRow-1) * gSquaresPerRow + gHoleColumn into holePosition
      setPicture getAt(gSquareList, holePosition), the memberNum of sprite pSpriteOfSquare
      -- assign hole cast member (it's right after all gamepiece pictures)
      -- to my sprite
      set the memberNum of sprite pSpriteOfSquare to gNumberOfSquares
      -- copy my location to hole location globals
      put pColumnOfSquare into gHoleColumn
      put pRowOfSquare into gHoleRow
      -- force redraw
      updateStage
    end
    on setPicture me, memberNumber
      set the memberNum of sprite pSpriteOfSquare to memberNumber
    end
    
  4. Verify that the syntax of this script is correct as well.

| return to outline |


Modify the frame script to capture mouse clicks

Individual scripts can contain multiple handers, and the handlers can be added at any time.

  1. Double-click on the first frame cell of the script channel  in the score to re-open the frame script in the script window.
    the first frame script in the Score

  2. Click to place the insertion point at the end of the script, after the handler that's already there. Enter the new handler so that the entire script reads:

    on exitFrame
      -- this handler keeps the movie looping on this frame
      go to the frame
    end
    on mouseUp
      --The clickOn returns the sprite clicked, or 0 if stage clicked.
      --For this to work, the sprites must be active, i.e., they must
      --either have a script attached, or be marked editable in Score
      gameClick (the clickOn) -- handled in GamePlay script
    end
    
  3. Take care to verify your spelling once again.

| return to outline |


Create additional movie script with gameplay handlers

You may want to identify this movie script cast member by name (e.g., "gameplay"), so it is easier to locate. A name is only required for parent scripts, though.

  1. Click on the "plus" button of the script window  to create a blank new movie script. Check again that the title bar reports this as a movie script.

  2. Enter the following script:

    on gameClick whichSprite
      --this handler responds to user input based on the part
      --of the game board clicked
      global gSquareChannelStart, gSquareList
      if whichSprite < gSquareChannelStart then 
        beep 3 -- you clicked the frame of the gameboard
      else
        --find which Square location was clicked
        put whichSprite - gSquareChannelStart + 1 into position
        --tell the Square to respond to the click
        click getAt(gSquareList, position)
      end if
    end
    
  3. If this script is entered correctly, you are now ready to test the puzzle.

| return to outline |


Copyright 1996 by Sandro Corsi.
Last modified 4 OCT 96.