简体   繁体   中英

Why can pygame.event.get() only be called once per frame

I was writing a function to make it easy to detect a key press without having to use the for loop that is normally used:

for event in pygame.event.get():
        if event.type == KEYDOWN:
            if event.key == key:

And I found that the function that I had written didn't work, and this is because I have this test_for_quit function in all my projects that runs every frame. I've found this to be useful as I can just copy this into any program that I'm writing:

def test_for_quit():
    '''Shuts down the game if it's closed'''
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.quit()
                sys.exit()

Surprisingly this is the first game I've made since implementing that function to all my programs, that doesn't use key presses. But I found that the reason that the new function that I've written didn't work because pygame.event.get() had already been called in the test_for_quit function.

After some more testing I found that this method cannot be called twice, for instance:

while True:
    print(pygame.event.get())
    print() #Leaves an empty line
    print(pygame.event.get())

returns:

[<Event(17-VideoExpose {})>, <Event(16-VideoResize {'h': 600, 'size': (800, 600), 'w': 800})>, <Event(1-ActiveEvent {'gain': 0, 'state': 1})>, <Event(4-MouseMotion {'rel': (538, 315), 'pos': (537, 314), 'buttons': (0, 0, 0)})>]

[]

So why is it that pygame.event.get() can only be called once, this really intrigues me and I couldn't find anything about it on the internet?

Also I've decided to not continue using the test_for_quit function and the key_down function in favour of just using the traditional for loop.

event.get can be called as many times as you want. The matter is it does take the events out of the event queue - and is up to your program to consume them. When it is called a second time with no interval (pygame itself knows nothing about "frames" - you give the delay between frames) - all events are gone, and no others have been generated.

The documentation for event.get reads:

This will get all the messages and remove them from the queue. If a type or sequence of types is given only those messages will be removed from the queue.

If you are only taking specific events from the queue, be aware that the queue could eventually fill up with the events you are not interested.

You have two choices: keep your "copy and pasted" call to event.get and read the keyboard state by using other calls - pygame.key.get_pressed for one - or to use a smarter way to consume the events in the queue.

There are even ways to check for evetns on the event queue without consuming them - so you could place those calls before a call to events.get .

One is that the function itself allows you to specify event types you are interested in. So let's suppose you have a function to deal with mouse events and a function to deal with keybard events:

def do_keys():
    for event in pygame.event.get(KEYDOWN):
         ...

def do_mouse():
    for event in pygame.event.get((MOUSEMOTION, MOUSEBUTTONDOWN)):
        ..
def main():
    while True:
        do_keys()
        do_mouse()
        # discard other events:
        pygame.event.get()
        # draw secreen
        ...
        pygame.time.delay(...)

Or, which is even easier, you can simply assign the return value of the call to pygame.event.get to a variable - that will be a single list over which you can iterate as many times as you wish.

events = pygame.event.get()
for event in events():
    # treat some evetns here
# some other logic here
...
do_keyboard_things(events)

def do_keyboard_things(events):
    for event in events:
         ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM