Doubt about KeyPress in Pygame

1

I have a question regarding Pygame.

I'm starting to fiddle and I found a problem here. When I press the A (left) button, I move the image to the left, until everything is ok. But if you keep the key pressed it does not repeat the movement. I have to depress and press the key again.

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

GitHub link: link

I suppose it must be a pretty silly problem, but forgive me. I'm just learning and I'm curious about these things. I already learned how to play GitHub haha: d

My class code:

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)

Execution code:

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)
    
asked by anonymous 03.11.2017 / 18:25

2 answers

2

If you get the KEYDOWN as you are doing, it will repeat yes, but not evenly.

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

But before that - do you notice that you have some code repeated in your move_left? And when you have the other functions you're doing, will that code repeat itself in a whole bunch of places?

Then - in particular, calls pygame.display.flip() and time.sleep should be done ONLY in the program, near the end of your main loop (in this case "whle True"). Functions can vary, disenchanter something from the screen buffer, etc ... but just leave a call to refresh the screen, and a pause call to the next loop execution, which should happen every time, not only from once in a while.

If you do just that, you should improve a lot. (In particular it has another problem: you pause first by calling sleep, and after refresh the screen: that is, the player is looking at the old screen, and after the frame is that screen it's better to call pygame.time.delay instead of time.sleep , just to maintain consistency, but it will not make a difference in your game.

Make those changes, you should get better. Then look at the documentation of pygame.key.get_pressed as I mentioned: a single call returns which keys are pressed at that moment : you only copy some values from the list returned to your keys list: it already returns "True "or" False "depending on which key is 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 movement into the "main loop," only using state variables in your class. I had not noticed that you were doing separate updates within the method. With this integration to the main loop for the class animation, the rest of the game continues to function while the moveLeft is active.

    
03.11.2017 / 20:26
0

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

From the Python Crash Course source code:

link

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
    
04.11.2017 / 01:21