Faster Version of 'Pygame.Event.Get()'. Why Are Events Being Missed and Why Are the Events Delayed

Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?

[...] and have two for event in pygame.event.get() loops [..]"

That's the issue. 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.

Get the events once per frame and use them in multiple loops or pass the list or events to functions and methods where they are handled:

def handle_events(events):
for event in events:
# [...]

while run:

event_list = pygame.event.get()

# [...]

# 1st event loop
for event in event_list:
# [...]

# [...]

# 2nd event loop
for event in event_list:
# [...]

# [...]

# function which handles events
handle_events(event_list)

Pygame : Having trouble w/ multiple event.get() calls

pygame.event.get() removes the events from the queue (see pygame documentation).

So, some of the events are gotten in the main loop, and the others in the class, and you don't know where a specific event is gotten py pygame. So you miss some of the events.

To avoid that, call pygame.event.get() one time per frame, and use the same list for both main loop and SingleBullet:

class Singlebullet(object):

def shoot(self):
...
for e in events: # same events as in main loop

while running:
events = pygame.event.get()
for event in events:
...

Don't forget to set the list to [] the first frame if you get the events after calling Singlebullet.shoot() (the class will ask for an unexisting list).

PyGame is Freezing

See Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?. The issue is that pygame.event.get() is called twice:

def game():

# [...]

clock.tick(FPS)

# [...]

pygame.event.get()

# [...]

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

Note, pygame.event.get() gets all the messages and remove them from the queue. So the first call gets the messages, remove them and puts them nowhere. The 2nd call doesn't get any messages at all.

At least you would've to do a "delay" between the calls of pygame.event.get() (e.g. clock.tick(FPS)).

Delete the first call of pygame.event.get() and move the event loop to the begin of game:

def game():

clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
# [...]



Further note, it makes no sens to call pygame.quit() and to call pygame.display.update() after that. pygame.quit() uninitialize all pygame modules and causes all further calls to pygame operations to crash.

Don't forget to update the display in the game loop by either pygame.display.update() or pygame.display.flip().

Add a return value to the function game. Return True, when the game loop should continue and False when the application should stop:

def game(): 

returnCode = True

clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
returnCode = False

# [...]

for s in [spikeUp0, spikeDown0, BoneUp1, BoneDown1, BoneUp2, BoneDown2]:
if pygame.sprite.collide_rect(Dog, s):
returnCode = False

# [...]

return returnCode
run = True
while run:

run = game()
pygame.display.update()

pygame.quit()
sys.exit()

Throttle keypresses in pygame

To jump you have to use KEYDOWN instead of pygame.key.get_pressed(). Use pygame.key.get_pressed() to move but not to jump.

pygame.key.get_pressed() returns a sequence 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.

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 like jumping or spawning a bullet.

Make sure you only call pygame.get.event() once (see Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?):

    def get_input(self, event_list):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and keys[pygame.K_RIGHT]: pass
elif keys[pygame.K_LEFT]: self.direction.x = -1
elif keys[pygame.K_RIGHT]: self.direction.x = 1
else: self.direction.x = 0

for event in event_list:
if event.type == pygame.KEYDONW and event.key == pygame.K_SPACE:
self.jump()
# application loop
while run:
# event loop
event_list = pygame.get.event()
for event in event_list:
if event.type == pygame.QUIT:
# [...]

player.get_input(event_list)

The other option is to state if SPACE was pressed in previous frames. So you can detect that the SPACE is hold down:

def __init__(self, pos):
super().__init__()
# [...]

self.space_was_pressed = False

def get_input(self):
keys = pygame.key.get_pressed()
# [...]

space_is_pressed = keys[pygame.K_SPACE]
if space_is_pressed and not self.space_was_pressed:
self.jump()
self.space_was_pressed = space_is_pressed

See also How to make a character jump in Pygame?

How To Make An Action Happen Only Once In Python / Pygame

First of all why do you not only allow to jump if self.on_ground?

class Player(pygame.sprite.Sprite):
# [...]

def get_input(self):
# [...]

if keys[pygame.K_SPACE] and self.on_ground:
self.jump()

Anyway, you have to use the KEYDOWN event instead of pygame.key.get_pressed()

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.

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.

class Player(pygame.sprite.Sprite):
# [...]

def get_input(self):

keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
self.direction.x = 1
elif keys[pygame.K_LEFT]:
self.direction.x = -1
else:
self.direction.x = 0

for event in event_list:
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
self.jump()
# application loop
while run:

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

# [...]

Note, 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.

See Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?.


Alternatively you can prevent multiple jumps in a row with a state attribute:

class Player(pygame.sprite.Sprite):
def __init__(self, pos):
# [...]
self.is_jumping = False

def get_input(self):

keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
self.direction.x = 1
elif keys[pygame.K_LEFT]:
self.direction.x = -1
else:
self.direction.x = 0

space_pressed = keys[pygame.K_SPACE]:
if space_pressed and not self.is_jumping:
self.jump()
self.is_jumping = space_pressed

pygame not blitting images onto the surface permanently

You must draw the scene in the application loop. The event loop is only executed once, when the event occurs. Add a state draw_scene = 0. Change the state when the event occurs (draw_scene = 1) and draw the scene depending on draw_scene.

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.

Get the events once per frame and use them in multiple loops. See Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?

draw_scene = 0
running = True
while running:
screen.fill((211, 211, 211))
alphaval -= 20

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

if draw_scene == 0:
screen.blit(frame_0, (0, 0))
pygame.draw.rect(screen, (0, 0, 0), (0, 0, 320, 480), 15)
if realtime >= 1:
loading(337, 99)
fadein()
if realtime <= 9 and realtime >= 3:
channel1.play(pygame.mixer.Sound('missions\call.ogg'))
time.sleep(9)
elif realtime >= 9:
screen.blit(frameE_0, (320, 0))
pygame.draw.rect(screen, (0, 0, 0), (320, 0, 320, 480), 15)
if realtime >= 12.5:
screen.blit(dialE, (45, 300))
textbox("hello?", 65, 340)
if realtime >= 14:
textbox("who is this?", 125, 340)

for event in event_list:
if event.type == pygame.KEYDOWN and realtime >= 14:
if event.key == pygame.K_RETURN:
draw_scene = 1

if draw_scene == 1:
screen.fill((211, 211, 211))
screen.blit(frame_0, (0, 0))
pygame.draw.rect(screen, (0, 0, 0), (0, 0, 320, 480), 15)
screen.blit(frameE_0, (320, 0))
pygame.draw.rect(screen, (0, 0, 0), (320, 0, 320, 480), 15)

pygame.display.update()
clock.tick(30)

Pygame is only drawing one button at a time

Yes of course, because you have an extra while-loop in the method draw_button. You have an application loop. Use it! You don't need the while loop in draw_button at all.

You will also need to remove the display update from draw_button. One update of the display at the end of the application loop is sufficient. Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering.

See Why is the PyGame animation is flickering

Next you will have problems with the events. pygame.event.get() get all the messages and remove them from the queuepygame.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.

Get the events once and use them in multiple loops or pass the list or events to functions and methods where they are handled.

See Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?.

def draw_button(button, outline, active, inactive, event_list, action=None):

mouse_pos = pygame.mouse.get_pos()
if button.isOver(mouse_pos):
button.color = active
else:
button.color = inactive

button.draw(screen, outline)

for event in event_list:
if event.type == pygame.MOUSEBUTTONDOWN:
if action and button.isOver(event.pos):
action()
def titlescreen():
active = True

start_button = button(buttonnormal, 240, 380, 150, 50, "START")
quit_button = button(buttonnormal, 420, 380, 150, 50, "quit")

while active:

event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
exit_game()

screen.fill(background)
title_text('Welcome To')
titleimage()

draw_button(start_button, black, btn_hover, buttonnormal, event_list, mainmenu)
draw_button(quit_button, black, btn_hover, buttonnormal, event_list, exit_game)

pygame.display.update()
clock.tick(60)


Related Topics



Leave a reply



Submit