Trying to delay a specific function for spawning enemy after a certain amount of time - python

I am making a mole shooter game using pygame. I want my mole to spawn at a random position after every 1 second. I have tried using time.sleep(1.0) but that delays my whole code and thus the game doesn't function properly because of delayed responses. I am moving an aim using the mouse(which also gets affected because of time.sleep) to which i will be adding a click to shoot. I need help with delaying and spawning my mole. I would also like some opinions on how to organize my code to provide various levels of difficulty and a main menu later on.
import pygame
import random
import time
from threading import Timer
pygame.font.init()
win_width = 1000
win_height = 710
FPS = 60
screen = pygame.display.set_mode((win_width, win_height))
pygame.display.set_caption("Mole Shooter")
white = (255,255,255)
red = (255, 0, 0)
counter, text = 30, 'Time Left: 30'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.Font('freesansbold.ttf', 32)
run = True
clock = pygame.time.Clock()
background = pygame.transform.scale(pygame.image.load('back_land.png'), (win_width, win_height))
aim = pygame.image.load("aim.png")
mole = pygame.image.load("mole.png")
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
screen.blit(mole, (molex, moley))
while run:
screen.blit(background, [0,0])
ax, ay = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
time.sleep(1.0);mole_spawn_easy()
else:
print("game over")
break
screen.blit(aim, ((ax - 32 ),(ay - 32)))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
clock.tick(FPS)
pygame.display.flip()

In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create a USEREVENT in the event queue.. The time has to be set in milliseconds:
pygame.time.set_timer(pygame.USEREVENT, 1000) # 1 second
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case the value of pygame.USEREVENT is the event id for the timer event.
Receive the event in the event loop:
running = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.USEREVENT:
# [...]
The timer event can be stopped by passing 0 to the time argument of pygame.time.set_timer.
See also Spawning multiple instances of the same object concurrently in python.
Create a list of moles and add a random position to the list in mole_spawn_easy:
moles = []
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
moles.append((molex, moley))
Draw the moles in the main application loop:
while run:
# [...]
for pos in moles:
screen.blit(mole, pos)
See the example:
moles = []
def mole_spawn_easy():
molex = random.randint(50, 950)
moley = random.randint(450, 682)
moles.append((molex, moley))
pygame.time.set_timer(pygame.USEREVENT, 1000)
while run:
ax, ay = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.USEREVENT:
counter -= 1
text = ("Time Left: " + str(counter)).rjust(3)
if counter > 0:
mole_spawn_easy()
else:
print("game over")
screen.blit(background, [0,0])
for pos in moles:
screen.blit(mole, pos)
screen.blit(aim, ((ax - 32 ),(ay - 32)))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(FPS)

Related

My pygame timer keeps resetting after I hit a target in my aim game

I am trying to make an aim game where a target pops up and once the player clicks on it, the target vanishes and a new one appears in a random location, I want it so that there is a 10 second timer but it keeps going back to 10 each time a target is "hit"
import pygame, random as r, time
FPS = 60
WIDTH = 900
HEIGHT = 500
WHITE = 255,255,255
BG = 26,26,26
RANGEXMIN = 20
RANGEXMAX = 840
RANGEYMIN = 20
RANGEYMAX = 440
window = pygame.display.set_mode((WIDTH, HEIGHT))
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
pygame.font.init()
FONT = pygame.font.Font('slkscr.ttf', 50)
def aim_train():
def new_target(countdown,text):
clock = pygame.time.Clock()
x = r.randint(RANGEXMIN, RANGEXMAX)
y = r.randint(RANGEYMIN, RANGEYMAX)
hit = False
while not hit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.USEREVENT:
if event.type == tick:
countdown= countdown - 1
text = str(countdown)
clock.tick(FPS)
window.fill(BG)
timer = FONT.render(text, False, WHITE)
window.blit(timer, (435, 20))
pygame.mouse.set_visible(False)
pos = pygame.mouse.get_pos()
pos_x = pos[0]
pos_y = pos[1]
target = pygame.draw.rect(window, WHITE, (x,y,50,50))
cursor_outline = pygame.draw.circle(window, BG, (pos_x,pos_y), 11)
cursor = pygame.draw.circle(window, WHITE,(pos_x,pos_y) ,10)
hit = (pygame.mouse.get_pressed()[0] and target.colliderect(cursor_outline))
pygame.display.update()
run = True
countdown = 10
text = str(countdown)
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.fill(BG)
pygame.mouse.set_visible(False)
new_target(countdown,text)
pygame.quit()
aim_train()
The variable "counter" somehow gets reset back to 10 after ever successful hit on a target
The problem is that you use a seperate function, new_target, for each target.
The countdown variable is defined inside the scope of the function aim_train. Because the new_target function is defined inside the aim_train function, it is a nested function and it can use all the variables that are defined inside aim_train. However, the new_target function still has its own scope. It can make changes to any variables defined inside aim_train, but those changes remain in its own scope. When a call of new_target is ended, its scope is discarded and all changes to the variables of aim_target are undone. This causes the countdown variable to be reset every in new call of new_target and thus every time a new target is created.
You might also have noticed that you can't close your window. The window doesn't react to clicking the red cross. This is because the same applies to the run variable. When you click the red cross, the run variable is set to True inside new_target, but not in the scope of aim_train. As such, the main loop in aim_train is not quitted and the program continues.
As a solution to this problem, I would recommend to include all the code of new_target into the aim_train function. Then you only have one function, which makes that all changes to variables are in the same scope and no changes are discarded:
import pygame, random as r, time
pygame.init()
FPS = 60
WIDTH = 900
HEIGHT = 500
WHITE = 255,255,255
BG = 26,26,26
RANGEXMIN = 20
RANGEXMAX = 840
RANGEYMIN = 20
RANGEYMAX = 440
window = pygame.display.set_mode((WIDTH, HEIGHT))
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
pygame.font.init()
FONT = pygame.font.SysFont('arial', 50)
def aim_train():
run = True
hit = False
countdown = 10
text = str(countdown)
x = r.randint(RANGEXMIN, RANGEXMAX)
y = r.randint(RANGEYMIN, RANGEYMAX)
clock = pygame.time.Clock()
pygame.mouse.set_visible(False)#switched
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == tick: #changed
countdown= countdown - 1
text = str(countdown)
window.fill(BG)
timer = FONT.render(text, False, WHITE)
window.blit(timer, (435, 20))
pos = pygame.mouse.get_pos()
pos_x = pos[0]
pos_y = pos[1]
target = pygame.draw.rect(window, WHITE, (x,y,50,50))
cursor_outline = pygame.draw.circle(window, BG, (pos_x,pos_y), 11)
cursor = pygame.draw.circle(window, WHITE,(pos_x,pos_y) ,10)
hit = (pygame.mouse.get_pressed()[0] and target.colliderect(cursor_outline))
if hit:
hit = False
x = r.randint(RANGEXMIN, RANGEXMAX)
y = r.randint(RANGEYMIN, RANGEYMAX)
pygame.display.update()
pygame.quit()
aim_train()
Apart from fixing the problem, I have also restructured your code a bit and did the following changes:
I have changed:
elif event.type == pygame.USEREVENT:
if event.type == tick:
into:
elif event.type == tick:
Outside of the aim_train function, you have stated that tick and pygame.USEREVENT are equal. As such, it is useless to compare to them two times, because if the first check is true, then the second one will certainly be.
I've placed pygame.mouse.set_visible(False) outside of the main loop.
Calling the function sets the mouse invisible untill another call changes sets the mouse back to visible. As such, it is useless to call it multiple times in the loop.
There are actually 2 countdown variables, one in the new_target function and one in the aim_train function. If you change the variable countdown in the new_target function, this will not change the variable countdown in the aim_train function. You must return the new value of countdown from the new_target function:
def aim_train():
def new_target(countdown):
# [...]
while not hit:
for event in pygame.event.get():
# [...]
elif event.type == pygame.USEREVENT:
if event.type == tick:
countdown= countdown - 1
# [...]
return countdown
run = True
countdown = 10
while run:
# [...]
countdown = new_target(countdown)
However, I suggest that you restructure your code. Do not use nested application loops. Also see Pygame mouse clicking detection:
import pygame, random as r
FPS = 60
WIDTH = 900
HEIGHT = 500
WHITE = 255,255,255
BG = 26,26,26
RANGEXMIN = 20
RANGEXMAX = 840
RANGEYMIN = 20
RANGEYMAX = 440
window = pygame.display.set_mode((WIDTH, HEIGHT))
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
pygame.font.init()
FONT = pygame.font.Font('slkscr.ttf', 50)
def new_target():
x = r.randint(RANGEXMIN, RANGEXMAX)
y = r.randint(RANGEYMIN, RANGEYMAX)
return x, y
def aim_train():
clock = pygame.time.Clock()
pygame.mouse.set_visible(False)
run = True
countdown = 10
hits = 0
countdownSurf = FONT.render(f'time {countdown}', False, WHITE)
hitsSurf = FONT.render(f'hits {hits}', False, WHITE)
target = pygame.Rect(0, 0, 50, 50)
target.center = new_target()
while run:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == tick:
countdown -= 1
countdownSurf = FONT.render(f'time {countdown}', False, WHITE)
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
if target.collidepoint(event.pos):
target.center = new_target()
hits += 1
hitsSurf = FONT.render(f'hits {hits}', False, WHITE)
pos = pygame.mouse.get_pos()
window.fill(BG)
window.blit(countdownSurf, countdownSurf.get_rect(center = (300, 45)))
window.blit(hitsSurf, hitsSurf.get_rect(center = (600, 45)))
pygame.draw.rect(window, WHITE, target)
pygame.draw.circle(window, BG, pos, 11)
pygame.draw.circle(window, WHITE, pos, 10)
pygame.display.update()
pygame.quit()
aim_train()

Adding cooldown to pygame animation [duplicate]

I started using pygame and I want to do simple game. One of the elements which I need is countdown timer.
How can I do the countdown time (eg 10 seconds) in PyGame?
Another easy way is to simply use pygame's event system.
Here's a simple example:
import pygame
pygame.init()
screen = pygame.display.set_mode((128, 128))
clock = pygame.time.Clock()
counter, text = 10, '10'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.SysFont('Consolas', 30)
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'boom!'
if e.type == pygame.QUIT:
run = False
screen.fill((255, 255, 255))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(60)
On this page you will find what you are looking for http://www.pygame.org/docs/ref/time.html#pygame.time.get_ticks
You download ticks once before beginning the countdown (which can be a trigger in the game - the key event, whatever).
For example:
start_ticks=pygame.time.get_ticks() #starter tick
while mainloop: # mainloop
seconds=(pygame.time.get_ticks()-start_ticks)/1000 #calculate how many seconds
if seconds>10: # if more than 10 seconds close the game
break
print (seconds) #print how many seconds
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:
timer_interval = 500 # 0.5 seconds
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event , timer_interval)
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case pygame.USEREVENT+1 is the event id for the timer event.
To disable the timer for an event, set the milliseconds argument to 0.
Receive the event in the event loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event:
# [...]
The timer event can be stopped by passing 0 to the time parameter.
See the example:
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 10
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
pygame.display.flip()
pygame.time.Clock.tick returns the time in milliseconds since the last clock.tick call (delta time, dt), so you can use it to increase or decrease a timer variable.
import pygame as pg
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 40)
gray = pg.Color('gray19')
blue = pg.Color('dodgerblue')
# The clock is used to limit the frame rate
# and returns the time since last tick.
clock = pg.time.Clock()
timer = 10 # Decrease this to count down.
dt = 0 # Delta time (time since last tick).
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
timer -= dt
if timer <= 0:
timer = 10 # Reset it to 10 or do something else.
screen.fill(gray)
txt = font.render(str(round(timer, 2)), True, blue)
screen.blit(txt, (70, 70))
pg.display.flip()
dt = clock.tick(30) / 1000 # / 1000 to convert to seconds.
if __name__ == '__main__':
main()
pg.quit()
There are several ways you can do this- here's one. Python doesn't have a mechanism for interrupts as far as I know.
import time, datetime
timer_stop = datetime.datetime.utcnow() +datetime.timedelta(seconds=10)
while True:
if datetime.datetime.utcnow() > timer_stop:
print "timer complete"
break
There are many ways to do this and it is one of them
import pygame,time, sys
from pygame.locals import*
pygame.init()
screen_size = (400,400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("timer")
time_left = 90 #duration of the timer in seconds
crashed = False
font = pygame.font.SysFont("Somic Sans MS", 30)
color = (255, 255, 255)
while not crashed:
for event in pygame.event.get():
if event.type == QUIT:
crashed = True
total_mins = time_left//60 # minutes left
total_sec = time_left-(60*(total_mins)) #seconds left
time_left -= 1
if time_left > -1:
text = font.render(("Time left: "+str(total_mins)+":"+str(total_sec)), True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
time.sleep(1)#making the time interval of the loop 1sec
else:
text = font.render("Time Over!!", True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
pygame.quit()
sys.exit()
This is actually quite simple. Thank Pygame for creating a simple library!
import pygame
x=0
while x < 10:
x+=1
pygame.time.delay(1000)
That's all there is to it! Have fun with pygame!
Another way to do it is to set up a new USEREVENT for a tick, set the time interval for it, then put the event into your game loop
'''
import pygame
from pygame.locals import *
import sys
pygame.init()
#just making a window to be easy to kill the program here
display = pygame.display.set_mode((300, 300))
pygame.display.set_caption("tick tock")
#set tick timer
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.USEREVENT:
if event.type == tick:
## do whatever you want when the tick happens
print('My tick happened')

python pygame window wont close "not responding"

I am trying to make a python window for my game from my laptop in pygame... however when I try to close the window I get an error message saying "not responding" im not sure why that if I thought i had done everything right.... the code is below any help is needed.
Thanks!
import pygame
from sys import exit
pygame.init()
screen = pygame.display.set_mode((800,400))
clock = pygame.time.Clock()
sky_surface = pygame.image.load("bg_desert.png").convert()
snail_surface = pygame.image.load("snailWalk1.png").convert_alpha()
player_surf = pygame.image.load("p1_walk01.png")
snail_x_pos = 600
while True:
pygame.time.set_timer(snail_x_pos, 100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("hello")
snail_x_pos -=4
if snail_x_pos < -100: snail_x_pos = 800
screen.blit(sky_surface,(0,0))
screen.blit(snail_surface,(snail_x_pos,350))
screen.blit(player_surf,(80, 200))
pygame.display.update()
clock.tick(60)
All problem makes
pygame.time.set_timer(snail_x_pos, 100)
which you run inside loop.
If I remove it then it closes without problem.
Every set_timer creates new timer which sends event every 100ms (again and again). If you run it in loop then you create hundreds timers.
You should run it only once - before loop - and it will repeatly send event which you can get in for-loop.
Problem is also that you use it in wrong way - you use snail position but it should user_id and time in milliseconds.
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 500) # 500ms = 0.5s
and later you can use it to move snail
elif event.type == my_event_id:
print('0.5 second')
snail_x_pos -= 4
Here my version with other changes.
I use Surfaces instead images so everyone can simply copy and run it.
I also use pygame.Rect to keep position and size - it has useful values (ie. .center to get/set center position) and functions (ie. to detect colisions). I use .left and .right to move snake to right side of window when it leaves window on left side.
import pygame
pygame.init()
screen = pygame.display.set_mode((800,400))
sky_surface = pygame.Surface((800, 100))
sky_surface.fill((0,0,255))
sky_surface_rect = sky_surface.get_rect()
snail_surface = pygame.Surface((100, 10))
snail_surface.fill((0,255,0))
snail_surface_rect = snail_surface.get_rect()
snail_surface_rect.x = 600
snail_surface_rect.y = 350
player_surf = pygame.Surface((10, 50))
player_surf.fill((255,0,0))
player_surf_rect = player_surf.get_rect()
player_surf_rect.x = 80
player_surf_rect.y = 200
clock = pygame.time.Clock()
my_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(my_event_id, 500) # 500ms = 0.1s
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
print("hello")
elif event.type == my_event_id:
print('0.5 second')
# move snake
snail_surface_rect.x -= 4
# use this event to slow down player
pressed = pygame.key.get_pressed()
if pressed[pygame.K_LEFT]:
player_surf_rect.x -= 4
elif pressed[pygame.K_RIGHT]:
player_surf_rect.x += 4
# - updates -
if snail_surface_rect.right < 0:
snail_surface_rect.left = 800
# - draw -
screen.fill((0,0,0)) # clear screen
screen.blit(sky_surface, sky_surface_rect)
screen.blit(snail_surface, snail_surface_rect)
screen.blit(player_surf, player_surf_rect)
pygame.display.update()
clock.tick(60)

Unable to start thread that plays sound [duplicate]

I started using pygame and I want to do simple game. One of the elements which I need is countdown timer.
How can I do the countdown time (eg 10 seconds) in PyGame?
Another easy way is to simply use pygame's event system.
Here's a simple example:
import pygame
pygame.init()
screen = pygame.display.set_mode((128, 128))
clock = pygame.time.Clock()
counter, text = 10, '10'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.SysFont('Consolas', 30)
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'boom!'
if e.type == pygame.QUIT:
run = False
screen.fill((255, 255, 255))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(60)
On this page you will find what you are looking for http://www.pygame.org/docs/ref/time.html#pygame.time.get_ticks
You download ticks once before beginning the countdown (which can be a trigger in the game - the key event, whatever).
For example:
start_ticks=pygame.time.get_ticks() #starter tick
while mainloop: # mainloop
seconds=(pygame.time.get_ticks()-start_ticks)/1000 #calculate how many seconds
if seconds>10: # if more than 10 seconds close the game
break
print (seconds) #print how many seconds
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:
timer_interval = 500 # 0.5 seconds
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event , timer_interval)
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case pygame.USEREVENT+1 is the event id for the timer event.
To disable the timer for an event, set the milliseconds argument to 0.
Receive the event in the event loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event:
# [...]
The timer event can be stopped by passing 0 to the time parameter.
See the example:
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 10
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
pygame.display.flip()
pygame.time.Clock.tick returns the time in milliseconds since the last clock.tick call (delta time, dt), so you can use it to increase or decrease a timer variable.
import pygame as pg
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 40)
gray = pg.Color('gray19')
blue = pg.Color('dodgerblue')
# The clock is used to limit the frame rate
# and returns the time since last tick.
clock = pg.time.Clock()
timer = 10 # Decrease this to count down.
dt = 0 # Delta time (time since last tick).
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
timer -= dt
if timer <= 0:
timer = 10 # Reset it to 10 or do something else.
screen.fill(gray)
txt = font.render(str(round(timer, 2)), True, blue)
screen.blit(txt, (70, 70))
pg.display.flip()
dt = clock.tick(30) / 1000 # / 1000 to convert to seconds.
if __name__ == '__main__':
main()
pg.quit()
There are several ways you can do this- here's one. Python doesn't have a mechanism for interrupts as far as I know.
import time, datetime
timer_stop = datetime.datetime.utcnow() +datetime.timedelta(seconds=10)
while True:
if datetime.datetime.utcnow() > timer_stop:
print "timer complete"
break
There are many ways to do this and it is one of them
import pygame,time, sys
from pygame.locals import*
pygame.init()
screen_size = (400,400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("timer")
time_left = 90 #duration of the timer in seconds
crashed = False
font = pygame.font.SysFont("Somic Sans MS", 30)
color = (255, 255, 255)
while not crashed:
for event in pygame.event.get():
if event.type == QUIT:
crashed = True
total_mins = time_left//60 # minutes left
total_sec = time_left-(60*(total_mins)) #seconds left
time_left -= 1
if time_left > -1:
text = font.render(("Time left: "+str(total_mins)+":"+str(total_sec)), True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
time.sleep(1)#making the time interval of the loop 1sec
else:
text = font.render("Time Over!!", True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
pygame.quit()
sys.exit()
This is actually quite simple. Thank Pygame for creating a simple library!
import pygame
x=0
while x < 10:
x+=1
pygame.time.delay(1000)
That's all there is to it! Have fun with pygame!
Another way to do it is to set up a new USEREVENT for a tick, set the time interval for it, then put the event into your game loop
'''
import pygame
from pygame.locals import *
import sys
pygame.init()
#just making a window to be easy to kill the program here
display = pygame.display.set_mode((300, 300))
pygame.display.set_caption("tick tock")
#set tick timer
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.USEREVENT:
if event.type == tick:
## do whatever you want when the tick happens
print('My tick happened')

Countdown timer is delayed on pygame screen? [duplicate]

I started using pygame and I want to do simple game. One of the elements which I need is countdown timer.
How can I do the countdown time (eg 10 seconds) in PyGame?
Another easy way is to simply use pygame's event system.
Here's a simple example:
import pygame
pygame.init()
screen = pygame.display.set_mode((128, 128))
clock = pygame.time.Clock()
counter, text = 10, '10'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.SysFont('Consolas', 30)
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'boom!'
if e.type == pygame.QUIT:
run = False
screen.fill((255, 255, 255))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(60)
On this page you will find what you are looking for http://www.pygame.org/docs/ref/time.html#pygame.time.get_ticks
You download ticks once before beginning the countdown (which can be a trigger in the game - the key event, whatever).
For example:
start_ticks=pygame.time.get_ticks() #starter tick
while mainloop: # mainloop
seconds=(pygame.time.get_ticks()-start_ticks)/1000 #calculate how many seconds
if seconds>10: # if more than 10 seconds close the game
break
print (seconds) #print how many seconds
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:
timer_interval = 500 # 0.5 seconds
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event , timer_interval)
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case pygame.USEREVENT+1 is the event id for the timer event.
To disable the timer for an event, set the milliseconds argument to 0.
Receive the event in the event loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event:
# [...]
The timer event can be stopped by passing 0 to the time parameter.
See the example:
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 10
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
pygame.display.flip()
pygame.time.Clock.tick returns the time in milliseconds since the last clock.tick call (delta time, dt), so you can use it to increase or decrease a timer variable.
import pygame as pg
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 40)
gray = pg.Color('gray19')
blue = pg.Color('dodgerblue')
# The clock is used to limit the frame rate
# and returns the time since last tick.
clock = pg.time.Clock()
timer = 10 # Decrease this to count down.
dt = 0 # Delta time (time since last tick).
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
timer -= dt
if timer <= 0:
timer = 10 # Reset it to 10 or do something else.
screen.fill(gray)
txt = font.render(str(round(timer, 2)), True, blue)
screen.blit(txt, (70, 70))
pg.display.flip()
dt = clock.tick(30) / 1000 # / 1000 to convert to seconds.
if __name__ == '__main__':
main()
pg.quit()
There are several ways you can do this- here's one. Python doesn't have a mechanism for interrupts as far as I know.
import time, datetime
timer_stop = datetime.datetime.utcnow() +datetime.timedelta(seconds=10)
while True:
if datetime.datetime.utcnow() > timer_stop:
print "timer complete"
break
There are many ways to do this and it is one of them
import pygame,time, sys
from pygame.locals import*
pygame.init()
screen_size = (400,400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("timer")
time_left = 90 #duration of the timer in seconds
crashed = False
font = pygame.font.SysFont("Somic Sans MS", 30)
color = (255, 255, 255)
while not crashed:
for event in pygame.event.get():
if event.type == QUIT:
crashed = True
total_mins = time_left//60 # minutes left
total_sec = time_left-(60*(total_mins)) #seconds left
time_left -= 1
if time_left > -1:
text = font.render(("Time left: "+str(total_mins)+":"+str(total_sec)), True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
time.sleep(1)#making the time interval of the loop 1sec
else:
text = font.render("Time Over!!", True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
pygame.quit()
sys.exit()
This is actually quite simple. Thank Pygame for creating a simple library!
import pygame
x=0
while x < 10:
x+=1
pygame.time.delay(1000)
That's all there is to it! Have fun with pygame!
Another way to do it is to set up a new USEREVENT for a tick, set the time interval for it, then put the event into your game loop
'''
import pygame
from pygame.locals import *
import sys
pygame.init()
#just making a window to be easy to kill the program here
display = pygame.display.set_mode((300, 300))
pygame.display.set_caption("tick tock")
#set tick timer
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.USEREVENT:
if event.type == tick:
## do whatever you want when the tick happens
print('My tick happened')

Categories