7 Replies Latest reply on Jan 11, 2011 8:23 AM by Roland684

    [as2] counteract buffered keyrepeat

    Roland684

      I'm moving an movieclip using the cursor keys. The device it has to run on, is too slow to process the keys realtime, so the keys are placed in a some sort of buffer and the object keeps on moving for a while when the key is released.
      The device places 8 keys in the buffer per second, but flash can only process 5 per second, so holding the key for a second, will look like I've pressed it almost twice as long.

       

      Does anyone know of a way to counteract this?

       

      I've tried using Key.isDown, but that returns true, even though they key is released, until the buffer is emptied.

       

      I've tried using the onKeyDown event to start the movement and stop the movement using the onKeyUp event, but it seems like the onKeyUp event only occurs when the buffer becomes empty. Even when I remove the onKeyDown listener, it seems like the buffer only decreases 1 key per frame.
      It might have worked when there is no keyrepeat in the hardware, but that is not an option.

       

      It would be helpfull if there was a timestamp indicating when the key was pressed, or some way to clear the buffer, but I've not found one.

        • 1. Re: [as2] counteract buffered keyrepeat
          kglad Adobe Community Professional & MVP

          don't use a key listener for moving your object.

           

          you use a listener to initiate and terminate an enterframe or setInterval loop using Key.isDown() in the loop to detect which key is down and what to do.

          • 2. Re: [as2] counteract buffered keyrepeat
            Roland684 Level 1

            like so:

             

            function leftkey() { trace("Left key is "+(Key.isDown(37)?"Down":"Up")); }

            setInterval(leftkey,10);

             

            That doesn't work.

            It keeps reporting they key is down for a while after the key is released.

             

            P.S. I only use a single frame in my movie.

            • 3. Re: [as2] counteract buffered keyrepeat
              kglad Adobe Community Professional & MVP

              try:

               

              var keyLO:Object = {};

               

              keyLO.onKeyDown=function(){
              if(!loopStarted){
              loopStarted=true;
              clearInterval(loopI);

              loopF()
              loopI = setInterval(loopF,70);
              }
              }
              keyLO.onKeyUp=function(){
              loopStarted=false
              clearInterval(loopI);

              }
              Key.addListener(keyLO);

               

              function loopF(){
              if(Key.isDown(Key.LEFT)){
              // do whatever
              }
              }

              1 person found this helpful
              • 4. Re: [as2] counteract buffered keyrepeat
                Roland684 Level 1

                That is exactly what I meant with:

                I've tried using the onKeyDown event to start the movement and stop the movement using the onKeyUp event, but it seems like the onKeyUp event only occurs when the buffer becomes empty. Even when I remove the onKeyDown listener, it seems like the buffer only decreases 1 key per frame.

                It doesn't work. (I did try your exact code too)

                 

                I just see the onKeyDown event being called once every frame until the buffer is empty and only then the onKeyUp event is called.

                (when I remove the listener in the onKeyDown event, the listener isn't called, but it looks like still every frame only a single key is removed from the buffer and only when that is empty, the onKeyUp event occurs).

                 

                I've even build a delay in between frames to create time for the onKeyDown event to process multiple keys, (to empty the buffer, the movie runs at 25fps), but that doesn't work either, the onKeyDown events only happen once per 125 ms even when there is nothing to render. They occur at the same speed they were originally entered. It's as if flash pauses the input/events while rendering the frame (which takes 200ms) then takes the first event waiting and then continues playing back the rest at their original speed. (so if rendering a frame takes more than the 125ms at which interval the keypresses occur, the input is just delayed with that extra time)

                 

                Just to avoid misunderstandings: when I say keys, I don't mean seperate keypresses, I just press and hold the key only once. Just like any PC, after a short delay the key then starts repeating automatically.

                (One other thing: I'm using flash lite.)

                • 5. Re: [as2] counteract buffered keyrepeat
                  kglad Adobe Community Professional & MVP

                  the code i suggested works for any as version that supports the used classes/functions.  that should be fl 2.0 or better.

                   

                  in my code, it doesn't matter when Key.onKeyUp is called and the repeat rate of a held-key is irrelevant.  

                   

                  the onKeyUp can be and is triggered some time after a key is actually released.  onKeyUp is only used to clean up an unneeded loop.

                   

                  the frequency of the loop is dependent on your frame rate, setInterval() frequency and the device executing the code.

                  • 6. Re: [as2] counteract buffered keyrepeat
                    Roland684 Level 1

                    I agree, it should work, and on a PC it does.

                     

                    I've created a test movie that does 10 seconds of heavy rendering (at 0.9 fps) and then 10 seconds of very little load (which can run at 32fps, but the movie is set to 25) I've added logging with a timestamp which shows when the onKeyDown and onKeyUp events are triggered.

                     

                    I can see the keys being entered with the flashing led on the device, this always happens at 4 keys per second (I thought it was 8, but the led flashes twice per key)

                    I hold the key for 5 seconds, thus entering aproximately 20 'keys'

                     

                    FLASH_TRACE: [63076] Heavy load: true
                    -- this is where I physically press the button --

                    FLASH_TRACE: [65229] onKeyDown event triggered
                    FLASH_TRACE: [66331] onKeyDown event triggered
                    FLASH_TRACE: [66358] onKeyDown event triggered
                    FLASH_TRACE: [67514] onKeyDown event triggered
                    FLASH_TRACE: [68711] onKeyDown event triggered
                    FLASH_TRACE: [69903] onKeyDown event triggered

                    -- this is where I physically release the button --

                    FLASH_TRACE: [71006] onKeyDown event triggered
                    FLASH_TRACE: [72067] onKeyDown event triggered
                    FLASH_TRACE: [73198] onKeyDown event triggered
                    FLASH_TRACE: [73215] Heavy load: false
                    FLASH_TRACE: [73261] onKeyDown event triggered
                    FLASH_TRACE: [73303] onKeyDown event triggered
                    FLASH_TRACE: [73354] onKeyDown event triggered
                    FLASH_TRACE: [73398] onKeyDown event triggered
                    FLASH_TRACE: [73439] onKeyDown event triggered
                    FLASH_TRACE: [73478] onKeyDown event triggered
                    FLASH_TRACE: [73517] onKeyDown event triggered
                    FLASH_TRACE: [73558] onKeyDown event triggered
                    FLASH_TRACE: [73617] onKeyDown event triggered
                    FLASH_TRACE: [73659] onKeyDown event triggered
                    FLASH_TRACE: [73699] onKeyDown event triggered
                    FLASH_TRACE: [73735] onKeyDown event triggered
                    FLASH_TRACE: [73773] onKeyDown event triggered
                    FLASH_TRACE: [73815] onKeyUp event triggered

                     

                    I clearly see keys being added to the buffer at 4fps, but only removed from the buffer at the framerate the movie is rendering.

                     

                     

                    Adding a fast (1ms) interval does increase the rate at which the buffer is emptied, but only when there is 'some time left'.

                    When the rendering is done within the 1/25th of a second, the interval is triggered as fast as possible (every 6ms).

                    But when the desired framerate can not be matched, the interval is only triggered once in between frames.

                     

                    -- this is where I physically press the button --

                    FLASH_TRACE: [5069] onKeyDown event triggered
                    FLASH_TRACE: [5075] Key.isDown==true
                    FLASH_TRACE: [5132] Key.isDown==true
                    FLASH_TRACE: [6319] onKeyDown event triggered
                    FLASH_TRACE: [6426] Key.isDown==true
                    FLASH_TRACE: [7581] onKeyDown event triggered
                    FLASH_TRACE: [7601] Key.isDown==true
                    FLASH_TRACE: [8726] onKeyDown event triggered
                    FLASH_TRACE: [8733] Key.isDown==true

                    -- this is where I physically release the button --

                    FLASH_TRACE: [9892] onKeyDown event triggered
                    FLASH_TRACE: [9900] Key.isDown==true
                    FLASH_TRACE: [11038] onKeyDown event triggered
                    FLASH_TRACE: [11045] Heavy load: false
                    FLASH_TRACE: [11046] Key.isDown==true
                    FLASH_TRACE: [11099] onKeyDown event triggered
                    FLASH_TRACE: [11105] Key.isDown==true
                    FLASH_TRACE: [11134] onKeyDown event triggered
                    FLASH_TRACE: [11147] onKeyDown event triggered
                    FLASH_TRACE: [11154] onKeyDown event triggered
                    FLASH_TRACE: [11160] Key.isDown==true
                    FLASH_TRACE: [11184] onKeyDown event triggered
                    FLASH_TRACE: [11190] onKeyDown event triggered
                    FLASH_TRACE: [11197] onKeyDown event triggered
                    FLASH_TRACE: [11203] onKeyDown event triggered
                    FLASH_TRACE: [11210] onKeyDown event triggered
                    FLASH_TRACE: [11216] onKeyDown event triggered
                    FLASH_TRACE: [11223] onKeyDown event triggered
                    FLASH_TRACE: [11229] onKeyDown event triggered
                    FLASH_TRACE: [11235] onKeyDown event triggered
                    FLASH_TRACE: [11241] onKeyDown event triggered
                    FLASH_TRACE: [11247] onKeyDown event triggered
                    FLASH_TRACE: [11255] onKeyUp event triggered

                     

                    The wierdest thing is happening here:

                    The interval appears to speed up the onKeyDown events, but not trigger the interval itself??

                     

                    (I've also tried setting 5 intervals, but that makes no difference: the 5 intervals are all triggered, but only 1 key is removed, not 5)

                     

                    Anyway, I could make a small delay before doing the heavy rendering to create some time to remove a few frames from the buffer. but at 6ms per key, that's pretty expensive. In the most optimistic case, that would mean an extra 25ms wait to handle the 4 frames per second.

                    • 7. Re: [as2] counteract buffered keyrepeat
                      Roland684 Level 1

                      I made it workable by waiting for a specific time between frame renders.

                       

                      As stated above, 4 keys are entered every second but can only be pulled from the buffer at the speed of the movie (set to 25 fps). So adding a 4/25 delay makes it possible to read 4 keys from the buffer.

                      Too bad I have to waste/wait 20% of the already very limited processing power just to keep the keyboard input acceptable.