Doubt about Keypress in Pygame

Asked

Viewed 2,468 times

1

I have a question related to Pygame.

I’m starting to move and I found a problem here. When I press the button A(left) I make the image walk to the left, until then everything ok. But if I hold down the key it does not repeat the movement. I have to drop and press again the key.

Another thing, as I put a Sleep of 0.07, if I press the X key times in this time interval, it will repeat this movement X times, even if not with the key pressed.

Link to the Github: https://github.com/EmanoelFraguas/GitProject/tree/master/Python/Pok%C3%A9%20Engine

I imagine it must be a very silly problem, but forgive me. I’m just learning and I’m curious about these things. I even learned how to work Github haha :d

Code of my class:

class Arcanine(object):
    def __init__(self, name):
        self.name = name

    def moveLeft(self):
        for i in range(4):
            if i % 2 == 0:
                pygame.display.flip()
                screen.fill(0)
                screen.blit(mapa, mappos)
                arcapos[0] = arcapos[0] - 8
                screen.blit(arca1, arcapos)
                time.sleep(0.07)
            else:
                pygame.display.flip()
                screen.fill(0)
                screen.blit(mapa, mappos)
                arcapos[0] = arcapos[0] - 8
                screen.blit(arca2, arcapos)
                time.sleep(0.07)

Code of implementation:

while True:
    pygame.display.flip()
    screen.fill(0)
    screen.blit(mapa, mappos)
    screen.blit(arca2, arcapos) 

    for event in pygame.event.get():

        if event.type == pygame.KEYDOWN:
            if event.key == K_w:
                keys[0] = True
            elif event.key == K_s:
                keys[1] = True
            elif event.key == K_a:
                keys[2] = True
            elif event.key == K_d:
                keys[3] = True

        if event.type == pygame.KEYUP:
            if event.key == K_w:
                keys[0] = False
            elif event.key == K_s:
                keys[1] = False
            elif event.key == K_a:
                keys[2] = False
            elif event.key == K_d:
                keys[3] = False

        if keys[0]:
            pass
        elif keys[1]:
            pass
        if keys[2]:
            arca.moveLeft()
        elif keys[3]:
            pass    

        if event.type == pygame.QUIT:
            pygame.quit()
            exit(0)

2 answers

2


If you catch the KEYDOWN as it is doing, it will repeat yes, but not uniformly.

The ideal is to use pygame.key.get_pressed()

But before that - do you notice that you have some repeated code on your move_left? And that when you have the other functions you’re doing, that code will repeat in a lot more places?

So - in particular, the calls pygame.display.flip() and time.sleep should be done ONLY once in the program, near the end of its main loop (in this case the "whle True"). The functions can act.Variable variable, unmount thingOn the screen buffer, etc... but leave only one call to refresh the screen, and a pause call to the next loop run, which should happen every time, not only once in a while.

If you do just that, you should already improve enough. (In particular there is another problem: you pause first by calling Sleep, and afterward refreshes the screen: that is, the player keeps looking at the old screen, and after the frame is that the screen is refreshed - the right one is refresh the screen, and pause. You might as well call pygame.time.delay instead of time.sleep, just to maintain consistency, but it won’t make a difference in your game.

Make these changes, should already improve. Then see the documentation of pygame.key.get_pressed as I mentioned: a single call returns which keys are pressed at that moment: you just copy some values from the returned list to your list keys: it already returns "True" or "False" depending on the key being pressed.

class Arcanine(object):
    def __init__(self, name):
        self.name = name
        self.moving_counter = 0
        self.moving_method = None

    def moving_left(self):
        arcapos[0] = arcapos[0] - 8
        if self.moving_counter % 2 == 0:
            screen.blit(arca1, arcapos)
        else:
        screen.blit(arca2, arcapos)

    def moving(self):
        if not self.moving_counter:
            return
        screen.fill(0)
        screen.blit(mapa, mappos)
        self.moving_method()
        self.moving_counter -= 1

    def moveLeft(self):
        self.moving_method = self.moving_left
        self.moving_counter = 4


while True:
    screen.fill(0)
    screen.blit(mapa, mappos)
    screen.blit(arca2, arcapos) 

    pygame.event.pump()
    keys = pygame.keys.get_pressed()

    keys[0] = keys[K_w]
    keys[1] = keys[K_s]
    keys[2] = keys[K_a]
    keys[3] = keys[K_d]

    if keys[0]:
        pass
    elif keys[1]:
        pass
    if keys[2]:
        arca.moveLeft()
    elif keys[3]:
        pass    

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit(0)

    pygame.time.delay(70)
    pygame.display.flip()

This code, in addition to the above suggestions, integrates pause and continuous motion in the "main loop", only using state variables in its class. I hadn’t noticed that you were doing separate updates within the method. With this integration into the main loop for class animation, the rest of the game continues to work while the "moveLeft" is active.

  • About the time.sleep is because I make an animation, that every 0.07 I move 8 pixels to the side the coordinates of the image, and to each one I change the .pngto move the character’s legs giving movement. get_pressedI’ll do a search here. .

  • I just got here with the get_pressed(): press = pygame.key.get_pressed()
 if press[119] == 1:
 arca.moveUp() when I leave pressed this way it keeps moving.

  • 1

    it is, but do not use "119", use the same constants you use when checking the event: K_w, and etc... -- as someone, or yourself, seeing your code in two weeks, you will know that the "119" is corresponding to the "w" key"?

0

See this example of a game 'space Invader', the approach he uses is interesting. Basically when the player presses the button, it assigns a true flag, and disables that flag in the keyup (drop it). That is, in the code below, Ship.moving_right will be True while the player is pressing the right arrow key.

From the source code of the book Python Crash Course:

https://github.com/ehmatthes/pcc/blob/master/chapter_12/game_functions.py

def check_keydown_events(event, ai_settings, screen, ship, bullets):
    """Respond to keypresses."""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    elif event.key == pygame.K_SPACE:
        fire_bullet(ai_settings, screen, ship, bullets)

def check_keyup_events(event, ship):
    """Respond to key releases."""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False

Browser other questions tagged

You are not signed in. Login or sign up in order to post.