Search code examples
pythonpython-3.xpygame

Movement code not working in pygame 2.0.1


I am making a simple game in pygame. Everything seems to be running correctly and there are no errors, but the code to move the sprite doesn't seem to work. If I set the sprite to move automatically it works fine, so I think it's a problem with the key press detection system. Here's the main game loop:

running = True
while running:
    # basic game function checks
    pygame.display.flip()
    clock.tick(60)
    movementtest(testX, testY)

    # checking if the game has been closed
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                running = False

    # movement code
    if movingleft:
        testX -= testX
    if movingright:
        testX += testX
    if movingup:
        testY += testY
    if movingdown:
        testY -= testY
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                if not movingright:
                    movingleft = True
            if event.key == pygame.K_d:
                if not movingleft:
                    movingright = True
            if event.key == pygame.K_w:
                if not movingdown:
                    movingup = True
            if event.key == pygame.K_s:
                if not movingup:
                    movingdown = True
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a:
                movingleft = False
            if event.key == pygame.K_d:
                movingright = False
            if event.key == pygame.K_w:
                movingup = False
            if event.key == pygame.K_s:
                movingdown = False

Why isn't it detecting my key inputs? I will post the pre-loop code if needed.


Solution

  • pygame.event.get() get all the messages and remove them from the queue. See the documentation:

    This will get all the messages and remove them from the queue. [...]

    If pygame.event.get() is called in multiple event loops, only one loop receives the events, but never all loops receive all events. As a result, some events appear to be missed.

    Either implement a single event loop or get the events once per frame and use them in multiple loops:

    running = True
    while running:
        # [...]
    
        event_list = pygame.event.get():
    
        # checking if the game has been closed
        for event in event_list :
            if event.type == pygame.QUIT:
                running = False
            # [...]
    
        # [...]
    
        for event in event_list:
            # [...]
    

    Additionally, you need to change the player's position through constants, not the position itself:

    running = True
    while running:
        # [...]
    
        if movingleft:
            testX -= 1
        if movingright:
            testX += 1
        if movingup:
            testY -= 1
        if movingdown:
            testY += 1 
    

    However, the code can be simplified by using pygame.key.get_pressed() instead of the key board events.

    The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.

    pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:

    running = True
    while running:
        # basic game function checks
        pygame.display.flip()
        clock.tick(60)
        movementtest(testX, testY)
    
        # checking if the game has been closed
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    running = False
    
        # movement code
        keys = pygame.key.get_pressed()
        if key[pygae.K_a]:
            testX -= 1
        if key[pygae.K_d]:
            testX += 1
        if key[pygae.K_w]:
            testY -= 1
        if key[pygae.K_s]:
            testY += 1