Skip to main content
Engineering LibreTexts

8.17: Moving by Holding Down the Key

  • Page ID
    14593
    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

            # handle moving the piece because of user input
            if (movingLeft or movingRight) and time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ:
                if movingLeft and isValidPosition(board, fallingPiece, adjX=-1):
                    fallingPiece['x'] -= 1
                elif movingRight and isValidPosition(board, fallingPiece, adjX=1):
                    fallingPiece['x'] += 1
                lastMoveSidewaysTime = time.time()
    
            if movingDown and time.time() - lastMoveDownTime > MOVEDOWNFREQ and isValidPosition(board, fallingPiece, adjY=1):
                fallingPiece['y'] += 1
                lastMoveDownTime = time.time()
    

    Remember that on line 227 the movingLeft variable was set to True if the player pressed down on the left arrow key? (The same for line 233 where movingRight was set to True if the player pressed down on the right arrow key.) The moving variables were set back to False if the user let up on these keys also (see line 217 and 219).

    What also happened when the player pressed down on the left or right arrow key was that the lastMoveSidewaysTime variable was set to the current time (which was the return value of time.time()). If the player continued to hold down the arrow key without letting up on it, then the movingLeft or movingRight variable would still be set to True.

    If the user held down on the key for longer than 0.15 seconds (the value stored in MOVESIDEWAYSFREQ is the float 0.15) then the expression time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ would evaluate to True. Line 2's [265] condition is True if the user has both held down the arrow key and 0.15 seconds has passed, and in that case we should move the falling piece to the left or right even though the user hasn’t pressed the arrow key again.

    This is very useful because it would become tiresome for the player to repeatedly hit the arrow keys to get the falling piece to move over multiple spaces on the board. Instead, they can just hold down an arrow key and the piece will keep moving over until they let up on the key. When that happens, the code on lines 216 to 221 will set the moving variable to False and the condition on line 2 [265] will be False. That is what stops the falling piece from sliding over more.

    To demonstrate why the time.time() - lastMoveSidewaysTime > MOVESIDEWAYSFREQ returns True after the number of seconds in MOVESIDEWAYSFREQ has passed, run this short program:

    import time
    
    WAITTIME = 4
    begin = time.time()
    
    while True:
        now = time.time()
        message = '%s, %s, %s' % (begin, now, (now - begin))
        if now - begin > WAITTIME:
            print(message + ' PASSED WAIT TIME!')
        else:
            print(message + ' Not yet...')
        time.sleep(0.2) 
    

    This program has an infinite loop, so in order to terminate it, press Ctrl-C. The output of this program will look something like this:

    1322106392.2, 1322106392.2, 0.0 Not yet...
    1322106392.2, 1322106392.42, 0.219000101089 Not yet...
    1322106392.2, 1322106392.65, 0.449000120163 Not yet...
    1322106392.2, 1322106392.88, 0.680999994278 Not yet...
    1322106392.2, 1322106393.11, 0.910000085831 Not yet...
    1322106392.2, 1322106393.34, 1.1400001049 Not yet...
    1322106392.2, 1322106393.57, 1.3710000515 Not yet...
    1322106392.2, 1322106393.83, 1.6360001564 Not yet...
    1322106392.2, 1322106394.05, 1.85199999809 Not yet...
    1322106392.2, 1322106394.28, 2.08000016212 Not yet...
    1322106392.2, 1322106394.51, 2.30900001526 Not yet...
    1322106392.2, 1322106394.74, 2.54100012779 Not yet...
    1322106392.2, 1322106394.97, 2.76999998093 Not yet...
    1322106392.2, 1322106395.2, 2.99800014496 Not yet...
    1322106392.2, 1322106395.42, 3.22699999809 Not yet...
    1322106392.2, 1322106395.65, 3.45600008965 Not yet...
    1322106392.2, 1322106395.89, 3.69200015068 Not yet...
    1322106392.2, 1322106396.12, 3.92100000381 Not yet...
    1322106392.2, 1322106396.35, 4.14899992943 PASSED WAIT TIME!
    1322106392.2, 1322106396.58, 4.3789999485 PASSED WAIT TIME!
    1322106392.2, 1322106396.81, 4.60700011253 PASSED WAIT TIME!
    1322106392.2, 1322106397.04, 4.83700013161 PASSED WAIT TIME!
    1322106392.2, 1322106397.26, 5.06500005722 PASSED WAIT TIME!
    Traceback (most recent call last):
        File "C:\timetest.py", line 13, in <module>
            time.sleep(0.2)
    KeyboardInterrupt
    

    The first number on each line of output is the return value of time.time() when the program first started (and this value never changes). The second number is the latest return value from time.time() (this value keeps getting updated on each iteration of the loop). And the third number is the current time minus the start time. This third number is the number of seconds that have elapsed since the begin = time.time() line of code was executed.

    If this number is greater than 4, the code will start printing "PASSED WAIT TIME!" instead of "Not yet...". This is how our game program can know if a certain amount of time has passed since a line of code was run.

    In our Tetromino program, the time.time() – lastMoveSidewaysTime expression will evaluate to the number of seconds that has elapsed since the last time lastMoveSidewaysTime was set to the current time. If this value is greater than the value in MOVESIDEWAYSFREQ, we know it is time for the code to move the falling piece over one more space.

    Don’t forget to update lastMoveSidewaysTime to the current time again! This is what we do on line 7 [270].

    Lines 9 [272] to 11 [274] do almost the same thing as lines 2 [265] to 7 [270] do except for moving the falling piece down. This has a separate move variable (movingDown) and "last time" variable (lastMoveDownTime) as well as a different "move frequency" variable (MOVEDOWNFREQ).


    This page titled 8.17: Moving by Holding Down the Key is shared under a CC BY-NC-SA 3.0 license and was authored, remixed, and/or curated by Al Sweigart via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.