4 Replies Latest reply on Jul 31, 2006 10:42 AM by wischoen

    buggy keyboard nav...

    wischoen Level 1
      Hi. I'm making a presentation in Director mx 2004 and using the keyboard only as navigation. the problem is, the keys are VERY slow and usually completely unresponsive. here's what I have set up:

      on exitFrame

      if (keyPressed("j")) then goDown
      if (keyPressed("u")) then goUp
      if (keyPressed("g")) then goToFrameByIndex

      end

      (if the user pressed 'u', the selection moves up, j goes down, and g executes whatever action is currently selected.)

      is this the best scheme for keyboard nav? how could I improve this code so that the keys work reliably and quickly?

      also, I plan to link the selected sprite to a movie sprite. for example: if the word "jupiter" is currently selected, then a small looping quicktime movie of jupiter would be shown elsewhere on the stage. arrow down, then a different movie appears. this seems to make the navigation even slower. i can post the rest of my code if you need.

      thanks for any help.
        • 1. Re: buggy keyboard nav...
          James Newton, ACP Level 3
          You could create a "Key Manager" Parent Script which detects when a key is pressed. You could use the keyDownScript to call a handler in your parent script:

          the keyDownScript = "script("&QUOTE&"Key Manager"&QUOTE&").keyDown()"
          the keyUpScript = "script("&QUOTE&"Key Manager"&QUOTE&").keyUp()"

          In the keyDown() handler, you could add the key the user pressed to a list of pressed keys. In the keyUp() handler, you could check which of the pressed keys has now been released. You now have a list which indicates which keys the user is holding down at any given time.

          In pseudo-Lingo:

          property plKeysPressed

          on new(me)
            plKeysPressed = []
          end

          on keyDown(me)
            add the current key to plKeysPressed
          end

          on keyUp(me)
            check which keys have been released and remove them from plKeysPressed
          end

          on shareKeyList(me)
            return plKeysPressed
          end

          Now, any other script or instance can use ShareKeyList() to obtain a pointer to the list of pressed keys, and act on what it finds in that list. You could even add handlers to allow other scripts or instances to receive notification when a change to plKeysPressed occurs.
          • 2. Re: buggy keyboard nav...
            wischoen Level 1
            here is my code, but I'm getting a "variable used before assigned value" error:

            (in the movie script):

            the keyDownScript = "script("&QUOTE&"keyManager"&QUOTE&").keyDown()"
            the keyUpScript = "script("&QUOTE&"keyManager"&QUOTE&").keyUp()"

            keyMan = new(script "keyManager")

            (in a behavior):

            on exitFrame

            keyList = shareKeyList(keyMan) <---------- error here
            repeat with j = 1 to keyList.count
            case keyList[ i] of
            "u":
            goUp
            "j":
            goDown
            "g":
            goToFrameByIndex
            end case
            end repeat
            end

            (in the parent script):


            property plKeysPressed

            on new me
            plKeysPressed = []
            end

            on keydown me
            add plKeysPressed, the keyPressed
            end

            on keyUp me
            repeat with i = 1 to plKeysPressed.count
            if keyPressed(plKeysPressed[ i]) = FALSE then
            plKeysPressed.deleteOne(plKeysPressed[ i])
            end if
            end repeat
            end

            on shareKeyList me
            return plKeysPressed
            end

            any help is appreciated.
            • 3. buggy keyboard nav...
              James Newton, ACP Level 3
              Here's my version:

              -- KEY MANAGER --
              -- Uninstantiated parent script
              --
              ----------------------------------------------------------------------
              -- This uninstanciated script keeps a list of the keyCodes of all keys
              -- currently being pressed by the user. To access this list from
              -- other scripts use:
              --
              -- myListOfPressedKeys = script("Key Manager").Key_ShareList()
              --
              -- Watcher Expression
              -- ------------------
              -- put script("Key Manager").plKeysPressed
              -- [3, 8, 32] -- corresponds to u, j and g
              ----------------------------------------------------------------------


              property plKeysPressed -- list of keys currently pressed by user


              on Key_Start(me) -----------------------------------------------------
              -- ACTION: Initializes this uninstanciated script. You must call
              -- this once before calling Key_ShareList()
              --------------------------------------------------------------------

              the keyDownScript = me&".keyDown()"
              the keyUpScript = me&".keyUp()"

              plKeysPressed = []
              end Key_Start


              on Key_ShareList(me) -------------------------------------------------
              -- OUTPUT: Returns a pointer to the list of pressed keys
              --------------------------------------------------------------------

              return plKeysPressed
              end Key_ShareList


              on keyDown(me) -------------------------------------------------------
              -- SOURCE: Forwarded by the primary event handler
              -- ACTION: Adds the most recently pressed key to plKeysPressed
              --------------------------------------------------------------------

              vKeyCode = the keyCode

              if not plKeysPressed.findPos(vKeyCode) then
              plKeysPressed.append(vKeyCode)
              end if

              -- The #keyDown event is automatically passed to other scripts
              end keyDown


              on keyUp(me) ---------------------------------------------------------
              -- SOURCE: Forwarded by the primary event handler
              -- ACTION: Removes any keys which are no longer pressed from
              -- plKeysPressed
              --------------------------------------------------------------------

              i = plKeysPressed.count
              repeat while i
              vKeyCode = plKeysPressed.getAt(i)
              if not keyPressed(vKeyCode) then
              plKeysPressed.deleteAt(i)
              end if

              i = i - 1
              end repeat

              -- The #keyUp event is automatically passed to other scripts
              end keyUp



              -- BEHAVIOR SCRIPT --


              property plKeysPressed -- shared list of keys pressed by the user


              on beginSprite(me) ---------------------------------------------------
              -- ACTION: Get the Key Manager script to start tracking pressed
              -- keys, and shares its list
              --------------------------------------------------------------------

              vScript = script("Key Manager")

              vScript.Key_Start()
              plKeysPressed = vScript.Key_ShareList()
              end beginSprite


              on enterFrame(me) ----------------------------------------------------
              -- ACTION: Checks if the user is currently pressing the "u", "j" or
              -- "g" keys, and if so calls the appropriate handler
              --------------------------------------------------------------------

              if plKeysPressed.getPos(3) then -- "u" | "U"
              goUp

              else if plKeysPressed.getPos(8) then -- "j" | "J"
              goDown
              end if

              if plKeysPressed.getPos(32) then -- "g" | "G"
              goToFrameByIndex
              end if
              end enterFrame


              -- PLACE HOLDER HANDLERS --

              on goUp()
              put #goUp
              end


              on goDown()
              put #goDown
              end


              on goToFrameByIndex()
              put #goToFrameByIndex
              end


              1) Create a new movie
              2) Create two scripts with the scriptTexts shown above
              3) Place a QuickDraw rect sprite on the stage
              4) Drop the behavior on the sprite
              5) Run the movie
              6) Press various keys and check the output in the Message window

              I've made it so that you can't call both goUp() and goDown() by pressing multiple keys, but you can call either of these and goToFrameByIndex() at the same time. I'm not sure exactly what logic you are looking for.

              This technique is good for controlling a character with multiple key-presses, where the user may repeat an action by holding the key down for a time. It looks as if you are more concerned with detecting that a given key has been pressed a single time, and that you would want to ignore continued pressure on the key.

              If this is the case, then you should not be using exitFrame() or enterFrame() to poll for key presses. You could use a behavior that amalgamates code from both scripts:


              -- ONE PRESS BEHAVIOR --


              property plKeysPressed -- list of keys currently pressed by user


              on beginSprite(me) ---------------------------------------------------
              -- ACTION: Initializes this uninstanciated script. You must call
              -- this once before calling Key_ShareList()
              --------------------------------------------------------------------

              vSprite = sprite(me.spriteNum)

              the keyDownScript = vSprite&".keyDown()"
              the keyUpScript = vSprite&".keyUp()"

              plKeysPressed = []
              end beginSprite


              on keyDown(me) -------------------------------------------------------
              -- SOURCE: Forwarded by the primary event handler
              -- ACTION: Performs an action only if no other key is currently
              -- being pressed
              --------------------------------------------------------------------

              vKeyCode = the keyCode

              if not plKeysPressed.count then
              -- The user was not pressing any key
              case vKeyCode of
              3: -- "u"
              goUp
              8: -- "j"
              goDown
              32: -- "g"
              goToFrameByIndex
              end case
              end if

              if not plKeysPressed.getPos(vKeyCode) then
              -- Remember that this key is being pressed
              plKeysPressed.append(vKeyCode)
              end if
              end keyDown


              on keyUp(me) ---------------------------------------------------------
              -- SOURCE: Forwarded by the primary event handler
              -- ACTION: Removes any keys which are no longer pressed from
              -- plKeysPressed
              --------------------------------------------------------------------

              i = plKeysPressed.count
              repeat while i
              vKeyCode = plKeysPressed.getAt(i)

              if not keyPressed(vKeyCode) then
              plKeysPressed.deleteAt(i)
              end if

              i = i - 1
              end repeat
              end keyUp


              -- PLACE HOLDER HANDLERS --

              on goUp()
              put #goUp
              end


              on goDown()
              put #goDown
              end


              on goToFrameByIndex()
              put #goToFrameByIndex
              end
              • 4. Re: buggy keyboard nav...
                wischoen Level 1
                thank you so much! the movie works much better now, and the buttons aren't laggy.