1

I am making a game with snake-like movement. I think, that the best way to achieve a good result, is to make separate thread for handling user's keyboard input. Here is my function that i want to run in separate thread:

    def _handle_keyboard_input(self):
        while self.is_running:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        self._set_velocity(-1, 0)
                    elif event.key == pygame.K_RIGHT:
                        self._set_velocity(1, 0)
                    elif event.key == pygame.K_UP:
                        self._set_velocity(0, -1)
                    elif event.key == pygame.K_DOWN:
                        self._set_velocity(0, 1)

    def _set_velocity(self, x, y):
        self._velocity_x = x
        self._velocity_y = y

Although i worry, whether constantly looping through that while will load the CPU too much. I thought about adding pygame.time.delay() delays, but then I'm not sure if i will "hit" the right moment for the KEYDOWN event (graphic that i found on this site below).

Time interval for keyboard events

I don't want to use pygame.key.get_pressed() because i don't want to prioritize any keys (in example if left and up arrow were pressed at the same time, I would have to choose one of them).

What is the best approach to this?

selethen
  • 627
  • 1
  • 5
  • 7
  • Please note that [`pygame.event.get()`](https://www.pygame.org/docs/ref/event.html) from the queue. If you have multiple event loops (even in different threads) then you'll miss events! I cannot see any good reason for handling the events in a different thread. Move time consuming computations to a different thread, but not the event handling. The event handling is required for updates and timing, too. – Rabbid76 May 03 '20 at 11:28
  • 1
    In main thread i have `pygame.time.delay(500)` since I wan't the snake to move with that frequency, so this delay will block everything for a while and keyboard couldn't be handled – selethen May 03 '20 at 11:42
  • 1
    *I think, that the best way to achieve a good result, is to make separate thread for handling user's keyboard input* What makes you think that? – sloth May 03 '20 at 12:43
  • @sloth The fact, that the user input will constantly be handled, without any interruption. But i didn't realise that the pygame events are stored in a queue, now it makes less sense – selethen May 03 '20 at 14:39

1 Answers1

1

Note pygame.event.get() removes the events from the queue. If you have multiple event loops (even in different threads) then you'll miss events. It is unnecessary to handle the events more often then the display is update, because state changes become only "visible" after an update of the display. Since the events are stored in a queue, it is not necessary to get the events at the "right" moment, pygame.event.get() gets and removes all the pending events from the queue.

If you want to move the snake every 500 milliseconds, then I recommend to use pygame.time.Clock. The method tick returns the number of milliseconds that have been passed since the previous call.
Sum up the milliseconds and move the snake when sum exceeds 500:

clock = pygame.time.Clock()
count_ms = 0

FPS = 100
run = True
while run:
    passed_ms = clock.tick(FPS)

    # event loop
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        # [...]

    count_ms += passed_ms
    if count_ms >= 500:
        count_ms = count_ms % 500

        # move and draw snake
        # [...]

        pygame.display.flip()
Rabbid76
  • 202,892
  • 27
  • 131
  • 174