pygamekeyboardkeydownkeyup

Pygame event: key up event triggering without releasing key


I am trying to make a tetris game and below is my code to make the blocks move. I want the block to keep moving when an arrow key is held down and to stop when it is released. But when I run the code, it stops the block even if the key isn't released.

   def set_keyboard_dirs(cur_block, width, height, events): # events stores pygame.event.get() as I use it multiple times in my code
        global move_timer # only moves block one time per set number of frames
        cur_block.reset_collisions(height)
        for event in events:
            if event.type == pygame.KEYDOWN:  # sets magnitude and direction of movement
                if event.key == pygame.K_RIGHT:
                    cur_block.dir = (cur_block.length, 0)
                elif event.key == pygame.K_LEFT:
                    cur_block.dir = (-cur_block.length, 0)
                elif event.key == pygame.K_DOWN:
                    cur_block.dir = (0, cur_block.length)
                elif event.key == pygame.K_UP:
                    cur_block.rotate(height, width)
                elif event.key == pygame.K_SPACE: # just moves the block instantly to the bottom of the screen by equating it to a 'projection' already there. 
                    cur_block.shape = deepcopy(cur_block.projection)
            elif event.type == pygame.KEYUP:  # stops block from moving
                print(event.key) # I called this to see what's happening, and event.key is printed event when I didn't release the key. 
                cur_block.dir = (0, 0)

        cur_block.move()

Because of the above, the block moves one step at a time instead of continuously (for as long as they are holding it) like I want. How can I fix it please? The rest of the game works so I really want this to work too. Thanks a lot in advance.

EDIT: I have also tried setting controls using pygame.key.get_pressed() as follows:

def set_keyboard_dirs(cur_block, width, height):
    global move_timer, keys
    cur_block.reset_collisions(height)
    cur_block.dir = (0, 0)
    if keys[pygame.K_UP] or keys[pygame.K_w]:
        cur_block.rotate(height, width)
    elif keys[pygame.K_SPACE]:
        cur_block.shape = deepcopy(cur_block.projection)
    elif (keys[pygame.K_DOWN] or keys[pygame.K_s]) and 2 not in cur_block.collisions: # 1, 2, 3 are collisions in left, down and right directions
        cur_block.dir = (0, cur_block.length)
    elif (keys[pygame.K_RIGHT] or keys[pygame.K_d]) and 1 not in cur_block.collisions:
        cur_block.dir = (cur_block.length, 0)
    elif (keys[pygame.K_LEFT] or keys[pygame.K_a]) and 3 not in cur_block.collisions:
        cur_block.dir = (-cur_block.length, 0)
    else:
        print('ran reset') # this statement print even as i'm holding down a key for some reason
        cur_block.dir = (0, 0)
    if cur_block.dir != (0, 0) and move_timer == 0:
        cur_block.move()
        move_timer = 7

in the former case, if I remove the KEYUP event and in the latter case if I remove the else statement, the block moves continuously (but cannot stop) which also shows that it is those statements are what is causing the problem, I think. And this is the only place is my code where I define my cur_block.dir as well.


Solution

  • In your code the movement of the block is canceled if any key is released, not if the special key is released. You would have to implements special cases if on of the cursor keys is released:

    elif event.type == pygame.KEYUP:
        if event.key == pygame.K_RIGHT:
            # [...]
        elif event.key == pygame.K_LEFT:
            # [...]
        # [...]
    

    I recommend to set the movement direction, dependent on the key states which are returned by pygame.key.get_pressed():

    def set_keyboard_dirs(cur_block, width, height, events):
        global move_timer
        cur_block.reset_collisions(height)
    
        keys = pygame.key.get_pressed()
    
        cur_block = [0, 0]
        if key[pygame.K_RIGHT]:
            cur_block.dir[0] += cur_block.length
        if key[pygame.K_LEFT]:
            cur_block.dir[0] -= cur_block.length
        if key[pygame.K_DOWN]:
            cur_block.dir[1] += cur_block.length
        if key[pygame.K_UP]:
            cur_block.rotate(height, width)
        if key[pygame.K_SPACE]:
            cur_block.shape = deepcopy(cur_block.projection)
    
        cur_block.move()