Articles Archive
Articles Search
Director Wiki

PIN entry

December 5, 1999
by Pat McClellan

Dear Multimedia Handyman,

Your recent password article was helpful, but I need to create a PIN entry system similar to a Cash Station pad. There won't be a text field displaying the numbers entered. Instead, there will be a keypad like a touchtone phone. Users will press 4 buttons and then be sent to either the correct frame, or another frame if the number is wrong. How could I do this?

Peter Balinski

Dear Peter,

This PIN interface is very common in real life... I'm surprised I haven't gotten this question sooner! Here's how we'll do it. We'll create a behavior which goes onto the buttons. Everytime a button is pressed, it will add its own number to a list of numbers entered. When the list contains the right number of digits, then we'll check to see if the digits match the PIN... and then go to the appropriate frame. Here's the demo:

A sample movie is available for download in Mac or PC format. This is a D7 movie.

Whenever you've got a group of sprites working together like this, they'll need to communicate back and forth. For example, all of the number keys need to know what numbers have already been entered. Usually, you'll use either sendSprite or sendAllSprites for the messaging between sprites. However, there's a pretty cool undocumented thing about lists that we can use instead. Take a look at this:

listA = ["cat", "bird","dog"]
listB = listA
add listA, "fish"
put listB
-- ["cat", "bird", "dog", "fish"]

Note that I set listB = listA in the second line. After that, I alter listA and the change is reflected when I put listB. Why? The variable listA doesn't really contain the list. Rather, it's a pointer to a memory location where the list resides. So when I set listB = listA, I'm not setting listB = ["cat", "bird", "dog"], but rather I'm assigning it the same memory location pointer that listA has. So when I change the values of the list in that memory location, listB will return that new value. (I know this is a bit abstract, so I hope I didn't lose anybody.)

This only works for lists, not other variables. Take a look at what happens if I try to do it with strings:

varA = "cat, bird, dog"
varB = varA
put ",fish" after varA
put varB
-- "cat, bird, dog"

Clearly, varB is set to the value of varA, so when varA changes, that change is not reflected in varB.

So how can we use this obscure distinction? As the user enters digits, the numeral will get added to a list called pEntry. I'll pass the name of that list to all of the sprites -- but only one time. They'll all be pointing to the same list in memory. So I never need to communicate subsequently entered numerals. I can add the numeral to the list from any of the buttons, and all of them will keep track of what's been entered. We know that this only works for lists, so it would be nice if our PIN which must be compared to the pEntry was also in list format. The author enters the PIN in the getPropertiesDescriptionList dialog box as a string, so we'll need to convert that and pass it to the other sprites.

Here's the behavior:

-- PIN entry behavior
-- copyright © 1999, ZZP Online, LLC
-- free use for Director Online readers
property pMyNumeral, pPIN, pPINdigits, pEntry
on getPropertyDescriptionList me
  set pdlist to [:]
  addprop pdlist, #pMyNumeral, [#comment:"Which key?", ¬
    #format:#string, #default:"1", range:["1","2","3","4","5",¬
  addprop pdlist, #pPIN, [#comment:"PIN:", #format:#string, ¬
  return pdlist
end getPropertyDescriptionList
on mouseUp me
  if voidP(pEntry) then -- this is the first key press
    pEntry = []
    PINstringToList me
    sendAllSprites (#setPIN, pPIN, pEntry, pPINdigits)
  end if
  add pEntry, pMyNumeral
  put pPIN, pEntry
  if pEntry.count = pPINdigits then
    if pEntry = pPIN then
      go to frame "match"
      go to frame "noMatch"
    end if
  end if
on PINstringToList me
  pPINdigits = pPIN.char.count
  pinString = pPIN
  pPIN = []
  repeat with whichChar = 1 to pPINdigits
    pPIN[whichChar] = pinString.char[whichChar]
  end repeat
on setPIN me, pinList, entryList, pinDigits
  pPIN = pinList
  pEntry = entryList
  pPINdigits = pinDigits

In the mouseUp handler, I first check to see if pEntry is void. If so, we know that this is the first number to be pressed. That means that we need to take this opportunity to convert the PINstring to a list format, initialize pEntry as a list, and send this info out to the other sprites. The PINstringToList handler does just what its name suggests. It also counts the number of digits in the PIN, which we'll use in a minute. All of this data is passed to the other sprites in a single sendAllSprites call. Note that this is where the pEntry pointer to the list is passed along. Take a look at the setPIN handler. That's the handler which receives the message and sets (or resets) its properties.

After the initialization stuff is done, the mouseUp handler continues by adding that sprite's numeral to the pEntry list. It then checks to see if the list contains the right number of digits for the PIN. If so, it checks to see if pEntry = pPIN and sends the user to the appropriate frame.

Note that I hardcoded the frames you'll go to. I could easily have made those properties which the author sets, but this is very tedious because you'd have to set it twelve times, while the value is only important for the behavior instance on the last digit of the PIN. Still, it's a very easy thing to change in the behavior. You can do it if you prefer.

Good luck with your program, and I hope you'll find other creative ways to use that list pointer thing.

Patrick McClellan is Director Online's co-founder. Pat is Vice President, Managing Director for Jack Morton Worldwide, a global experiential marketing company. He is responsible for the San Francisco office, which helps major technology clients to develop marketing communications programs to reach enterprise and consumer audiences.

Copyright 1997-2019, Director Online. Article content copyright by respective authors.