Waiting Without Freezing Everything
Solution 1:
The problem is that you can´t get any events for the amount of time the game pauses when you use for instance the pygame.time.wait()
or pygame.time.delay()
functions of the PyGame time
module.
To avoid this problem you could create your very own event which appears on the event queue every given number of milliseconds. You could use pygame.time.set_timer()
to create an event:
import pygame
pygame.init()
#color tupels
BLUE = (55,155,255)
YELLOW = (255,255,0)
#create a new event id called event_500ms
event_500ms = pygame.USEREVENT + 1#set timer event to appear on the event queue every 500 milliseconds
pygame.time.set_timer(event_500ms, 500)
screen = pygame.display.set_mode((800,800))
#global variable V for state-machine
V = 0whileTrue:
#get events from the event queuefor ev in pygame.event.get():
if ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE:
pygame.quit()
exit()
#left (ev.button == 3) mousbutton down -> set variable V = 1if ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 3:
V = 1#check for the event_500ms event if ev.type == event_500ms:
if V == 1:
screen.fill(BLUE)
V = 2elif V == 2:
screen.fill(YELLOW)
V = 0
pygame.display.flip() #update whole screen
In this code we use a sort of a so-called state-machine with 3 different stages:
- Set
V = 1
, if apygame.MOUSEBUTTONDOWN
event accurse, (Next state: 2) - Fill the
screen
blue and incrementV
, if variableV
equals1
. (Next state: 3) - Fill the
screen
yellow and restV
to0
, if variableV
equals2
. (Next state: 1)
I hope this helps :)
Solution 2:
There a two solutions to you problem, which represents the both approaches you tried: Either you wait a specific time for your next tick or you do something each tick but then you have the problem that ticks are dependent on how fast the computer is (and other factors like programs running in the background). (With tick I refer to each run through your main loop, which you probably use.)
At the moment you say "okay, I want to change the background every fourth tick", with the problem that this might be every milisecond, or every second or whenever. So we need to not depend on the amount of ticks that happened but the amount of time. We can use time.perf_counter() to get the current time. This gives us:
#Initialize old_time somewhere
new_time = time.perf_counter()
if new_time - old_time > 0.05:
change_background()
old_time = new_time
Normally you don't want to do this for every thing that is time dependent. Instead as the first thing in your while loop calculate a delta time, often called dt
while True:
dt = time.perf_counter() - old_time
old_time = time.perf_counter()
change_background(dt)
Then handle the dt
the same way we handled it before:
def change_background(dt):
cumulative_time += dt
if cumulative_time > 0.05:
#do things
cumulative_time = 0
The other way would be to use some kind of sleep
. As you already saw this will freeze the whole thread - but you can create more than one (of course you don't need to use threads, you could use processes or greenlets or all that other fancy multiprocessing stuff). The whole thing is a bit complicated, so I will not go into details here, but generally it is a good idea to have different threads for input and processing. The relative new asyncio
module deals with exactly that kind of problem. There are also different solutions like greenlets or threads. Doing things asyncronuos can be confusing at the beginning, the first solution can take you relative far.
EDIT: My answer is independent of pygame, the events used in the other answer does this in the background for you. It is still a good idea to understand this delta time idea and to use it e.g. in physics computation. Generally being dependent on ticks (instead of time) is a bad idea and can give you unexpected behavior. It is said that the original space invaders did depend on ticks for their physics and graphics computations. Thus it sped up everytime you shoot enough enemies. This was an unexpected result (and then kept because it was a good mechanic to increase difficulty). The same problem is faced by emulators: Often old games (which depend on ticks and not on time) would run incredible fast because modern computers have much more processing power. An emulator has to take that into account and "slow processing down".
Solution 3:
Maybe you could try:
import timetime.sleep(5)
Post a Comment for "Waiting Without Freezing Everything"