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",¬ "6","7","8","9","0","*","#"]] addprop pdlist, #pPIN, [#comment:"PIN:", #format:#string, ¬ #default:"1234"] 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" else go to frame "noMatch" end if end if end on PINstringToList me pPINdigits = pPIN.char.count pinString = pPIN pPIN = [] repeat with whichChar = 1 to pPINdigits pPIN[whichChar] = pinString.char[whichChar] end repeat end on setPIN me, pinList, entryList, pinDigits pPIN = pinList pEntry = entryList pPINdigits = pinDigits end
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.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.