Simon Says

by Gary Rosenzweig

I was recently asked by a reader about making a game something like the old "Simon" game. This is where you would be shown a pattern of lights and sounds, and then asked to repeat it. Unfortunately, I didn't put a game like this in my games book. I guess you can't cover every base, but I thought it would make a good Lingo Lounge column.

Director 7 download for Mac or Windows.

A game like this should have two frames. The first will be one that shows the pattern. The second will then let the user repeat it. Even before these two frames, we can have one that explains the rules and lets players press a button to start. The frame script here will also be used to reset the pattern for the game. We'll store this pattern in a global.

global gPatternList

on exitFrame
  go to the frame
end

on mouseUp
  
  -- reset pattern
  gPatternList = []
  
  -- start the game
  go to frame "Play"
  
end

The "play" frame will add a new "light" to the pattern each time. This "light" will be either a red, green, or blue circle on the screen. We'll use three bitmaps. We'll have three "off" states of each light and three "on" states. So the light names will be something like "lightA on" and "lightA off".

When the "play" frame begins, it will add a random light to the pattern and kick off the timer that will control the display the lights. We'll assume that each light is in sprite 1 to 3, so the lights will be referred to in that list as 1, 2 or 3.

global gPatternList
property pNextTime
property pNextToShow

on beginSprite me
  add gPatternList, random(3)
  pNextToShow = 1
  pNextTime = the milliseconds
end

The "pNextTime" property is used to time the turning on and off of the lights. Each light is turned on for 500 milliseconds, and then all are off for another 500 milliseconds. This is repeated until the entire pattern is done. Then, the movie jumps to the "repeat" frame.

on exitFrame me
  
  if the milliseconds >= pNextTime then
    
    if pNextToShow > gPatternList.count then
      go to frame "repeat"
      exit
    else
      
      thisSpriteNum = gPatternList[pNextToShow]
      memName = sprite(thisSpriteNum).member.name
      
      if memName.word[2] = "on" then
        put "off" into memName.word[2]
        sprite(thisSpriteNum).member = member(memName)
        pNextToShow = pNextToShow + 1
      else
        put "on" into memName.word[2]
        sprite(thisSpriteNum).member = member(memName)
        puppetSound memName.word[1]&&"sound"
      end if
      
      pNextTime = the milliseconds + 500
    end if
    
  end if
  
  go to the frame
  
end

The "repeat" frame works in a similar way as the "play" frame, except that it waits for the user to click on each light instead of doing it automatically. When this happens, the light clicked is compared to the next light in the list. If they don't match, then the game is over. Otherwise, if the list is exhausted, then the game returns to the "play" frame for a longer pattern to be presented.

global gPatternList
property pNextToClick

on beginSprite me
  pNextToClick = 1
end


on clickSprite me, thisSpriteNum
  
  if thisSpriteNum = gPatternList[pNextToClick] then
    
    if pNextToClick = gPatternList.count then
      go to frame "Play"
    else
      pNextToClick = pNextToClick + 1
    end if
    
  else
    member("score").text = "Score:"&&(gPatternList.count-1)
    go to frame "End"
  end if
  
end

-- loop on the frame
on exitFrame me
  go to the frame
end

The "on clickSprite" handler is called from the behavior attached to the lights. Here is that behavior; it turns the light on "on mouseDown" and then off "on mouseUp" and reports this to the frame script.

property pMemName

on beginSprite me
  pMemName = sprite(me.spriteNum).member.name
end

on mouseDown me
  put "on" into pMemName.word[2]
  sprite(me.spriteNum).member = member(pMemName)
  puppetSound pMemName.word[1]&&"sound"
end

on mouseUp me
  put "off" into pMemName.word[2]
  sprite(me.spriteNum).member = member(pMemName)
  sendSprite(0,#clickSprite,me.spriteNum)
end

on mouseUpOutside me
  put "on" into pMemName.word[2]
  sprite(me.spriteNum).member = member(pMemName)
end

Once the player messes up, the movie goes to frame "end" where a simple script will take the user back to frame "start" when they want to play again. The final score is presented to the player at the end by simply looking at the length of the pattern list.