Thank you for your help on my last question, i managed to fix my error.
So i am continuing my small game and i would like the player to see how many points they get (briefly) when they defeat an enemy.
if bullet_rect.colliderect(enemy1_rect):
#enemy respawn
enemy1_rect.x = 1350
enemy1_rect.y = random.randint(0, 500)
#points won display
points += 100
points_rect = points_text.render('+ 100$', None, 'Green')
screen.blit(points_rect, bullet_rect)
This kind of works, but it only displays for just 1 frame!
I tried pygame.time.wait,delay,sleep, and i have come nowhere.
I would like for it to display for half a second, so maybe since i run the game at 60 FPS capped, display it for 30 frames.
Any suggestions? Thank you!
You need to draw the text in the application loop. Use pygame.time.get_ticks to measure time in milliseconds. Calculate the time when the text must vanish and display the text until the time is reached:
text_end_time = 0
text_rect = None
run = True
while run:
# [...]
current_time = pygame.time.get_ticks()
if bullet_rect.colliderect(enemy1_rect):
enemy1_rect.x = 1350
enemy1_rect.y = random.randint(0, 500)
points += 100
points_surf = points_text.render('+ 100$', None, 'Green')
text_end_time = current_time + 2000 # 2 seconds
text_rect = bullet_rect.copy()
if text_end_time > current_time
screen.blit(points_surf, text_rect)
See also Pygame "pop up" text and Adding a particle effect to my clicker game.
Related
I have an interesting problem. I need to make such that image must appear every random time in a random place and if it collides with my GAMER it must affect GAMER(some function) with GAMER for exactly 3 sec and disappear and appear after a random time again.
. I have an idea but it does not work.(note: this is a part of code i already initialized everythiing)
clock = pygame.time.Clock()
FPS = 30
playtime = 0
newtime=random.randint(3,10)
while mainloop:
milliseconds = clock.tick(FPS)
seconds = milliseconds / 1000.0
playtime += seconds
if playtime>=newtime:
image.draw()
newtime=random.randint(2,6) #because next appear time must change
if collision(GAMER,image):
GAMER.do_something() #how to do it exactly for 3 sec?
image.far_away() #just dissapear for some time
When you talk about an image, then you talk about a pygame.Surface. A pygame.Surface can be blit() to the display (respectively the Surface which is associated to the window). For instance
screen.blit(image, image_rect)
You cannot move a surface far away. You have to draw the entire scene in every frame and you have to draw (blit) the image on the display surface in every frame.
You can change the position of the image. Create a random position when the time span exceeds:
position = random.randint(0, window_height), random.randint(0, window_width)
image_rect = image.get_rect(center = position)
When the player collides with the image, then set compute the time point 3 seconds in the future. Effect the player as long the 3 seconds are not exceeded:
if image_rect.colliderect(GAMER.rect):
affecttime = playtime + 3
if playtime < affecttime:
GAMER.do_something()
General process:
clock = pygame.time.Clock()
FPS = 30
newtime=random.randint(3,10)
playtime = 0
affecttime = 0
position = random.randint(0, window_height), random.randint(0, window_width)
image_rect = image.get_rect(center = position)
while mainloop:
milliseconds = clock.tick(FPS)
seconds = milliseconds / 1000.0
playtime += seconds
# handle events (event loop)
for event in pygame.event.get():
if event.type == pygame.QUIT:
mainloop = False
if playtime >= newtime:
newtime = playtime + random.randint(2,6)
position = random.randint(0, window_height), random.randint(0, window_width)
image_rect = image.get_rect(center = position)
if image_rect.colliderect(GAMER.rect):
affecttime = playtime + 3
position = .... # set position far away
image_rect = image.get_rect(center = position)
if playtime < affecttime:
GAMER.do_something()
# clear dispaly
scree.fill(0)
#draw image at the current position
screen.blit(image, image_rect)
# update disaply
pygame.display.update()
I'm trying to create a program where balloons appear for the user to pop, however balloons are appearing so fast it becomes unmanageable. I took a screenshot about half a second into running the program:
Here is the code for time between balloons appearing:
timeTillNextBalloon = random.randint(100000, 200000)
while done == False:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if pygame.time.get_ticks() > timeTillNextBalloon:
timeTillNextBalloon = random.randint(30000, 250000)
yCoord = random.randint(50,350)
balloonType = random.randint(1,4)
balloon = Balloon(0, yCoord, "right", balloonType)
if balloonType >= 1 and balloonType <= 3:
otherBalloons.add(balloon)
else:
blueBalloons.add(balloon)
allBalloons.add(balloon)
I've tried to increase the timeTillNextBaloon variable, but it just shows a black screen if I try to make it any bigger than this.
Get_ticks gets the current time, timeTillNextBalloon should be the current to + the random value. Now every the loop repeats a balloon is added:
timeTillNextBalloon = pygame.time.get_ticks() + random.randint(30000, 250000)
I am creating a clicker game, very similar to cookie clicker. My question is, how do I increase a variable by an amount every second?
Here, prepare for a new game.
def new(self):
# set cookies/multipliers for a new game
self.cookie_count = 0
self.grandma = 10 # grandma bakes 10 cookies/second
Then, if a grandma is purchased, add 10 cookies/second to self.cookie_count for every grandma purchased. Example: If 2 grandmas are purchased, self.cookie_count += 20 cookies/second. Yet, as I have it now, everytime I purchase a grandma I just get 10 cookies.
if self.rect2.collidepoint(self.mouse_pos) and self.pressed1:
self.cookie_count += self.grandma
I know that it has something to do with time, but other than that I'm not quite sure where to start.
Instead of incrementing the cookies once per second, you can make the cookie count just how many seconds have passed since the start. This may cause problem in certain scenarios (this will complicate pausing, for example), but will work for simple games.
My Python is a tad rusty, so sorry if this isn't entirely idiomatic:
import time
self.start_time = time.time()
# When you need to know how many cookies you have, subtract the current time
# from the start time, which gives you how much time has passed
# If you get 1 cookie a second, the elapsed time will be your number of cookies
# "raw" because this is the number cookies before Grandma's boost
self.raw_cookies = time.time() - self.start_time
if self.grandma:
self.cookies += self.raw_cookies * self.grandma
else:
self.cookies += raw.cookies
self.raw_cookies = 0
This may look more complicated than just using time.sleep, but it has two advantages:
Using sleep in games is rarely a good idea. If you sleep on the animation thread, you'll freeze the entire program for the duration of the sleep, which is obviously not a good thing. Even if that's not an issue in simple games, the use of sleep should be limited for habit's sake. sleep should really only be used in tests and simple toys.
sleep isn't 100% accurate. Over time, the error of the sleep time will accumulate. Whether or not this is a problem though is entirely dependant on the application. By just subtracting the time, you know exactly (or at least with high precision) how much time has passed.
Note:
With the code above, cookies will be a floating point number, not an integer. This will be more accurate, but may not look nice when you display it. Convert it to an integer/round it before displaying it.
Having never player "Cookie Clicker" before, I may have confused the logic. Correct me if something doesn't make sense.
I'm assuming self.grandma is None/falsey if the player doesn't have the upgrade.
The way to do this in pygame is to use pygame.time.set_timer() and have an event generated every given number of milliseconds. This will allow the event to be handled in the script's main loop like any other.
Here's a somewhat boring, but runnable, example of doing something like that:
import pygame
pygame.init()
SIZE = WIDTH, HEIGHT = 720, 480
FPS = 60
BLACK = (0,0,0)
WHITE = (255,255,255)
GREEN = (0,255,0)
RED = (255,0,0)
BLUE = (0,0,255)
BACKGROUND_COLOR = pygame.Color('white')
screen = pygame.display.set_mode(SIZE)
clock = pygame.time.Clock()
font = pygame.font.SysFont('', 30)
COOKIE_EVENT = pygame.USEREVENT
pygame.time.set_timer(COOKIE_EVENT, 1000) # periodically create COOKIE_EVENT
class Player(pygame.sprite.Sprite):
def __init__(self, position):
super(Player, self).__init__()
self.cookie_count = 0
self.grandma = 10 # grandma bakes 10 cookies/second
text = font.render(str(self.cookie_count), True, RED, BLACK)
self.image = text
self.rect = self.image.get_rect(topleft=position)
self.position = pygame.math.Vector2(position)
self.velocity = pygame.math.Vector2(0, 0)
self.speed = 3
def update_cookies(self):
self.cookie_count += self.grandma # 10 cookies per grandma
if self.cookie_count > 499:
self.cookie_count = 0
text = font.render(str(self.cookie_count), True, RED, BLACK)
self.image = text
player = Player(position=(350, 220))
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == COOKIE_EVENT:
player.update_cookies()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player.velocity.x = -player.speed
elif keys[pygame.K_RIGHT]:
player.velocity.x = player.speed
else:
player.velocity.x = 0
if keys[pygame.K_UP]:
player.velocity.y = -player.speed
elif keys[pygame.K_DOWN]:
player.velocity.y = player.speed
else:
player.velocity.y = 0
player.position += player.velocity
player.rect.topleft = player.position
screen.fill(BACKGROUND_COLOR)
screen.blit(player.image, player.rect)
pygame.display.update()
You'll need to use time module. You can capture period of time with time.time().
import time
grandma = 3
cookie_count = 0
timeout = 1
while True:
cookie_count += grandma * 10
print 'cookie count: {}'.format(cookie_count)
time.sleep(timeout)
Another option is to validate the expression now - start > timeout. They will both do the same, but incase your timeout is larger than 1 this would be the solution. The first code above won't work.
import time
grandma = 3
cookie_count = 0
timeout = 1
start = time.time()
while True:
if time.time() - start > timeout:
cookie_count += grandma * 10
print 'cookie count: {}'.format(cookie_count)
time.sleep(timeout)
I have got a working digital clock in python but I am stuck trying to make it a visual in pygame.
The code for the clock works but it just doesn't display anything, even though I have used .blit to do so.
The idea is to have the timer show every minute (Second), Hour(every 60 seconds) and Days (Every 12 in game hours). This is then to appear on the top left.
Here is my code:
import sys, pygame, random, time
pygame.init()
#Screen
size = width, height = 1280, 720 #Make sure background image is same size
screen = pygame.display.set_mode(size)
done = False
#Animation
A1=0
A2=0
#Time Info
Time = 0
Minute = 0
Hour = 0
Day = 0
counter=0
#Colour
Black = (0,0,0)
White = (255, 255, 255)
#Fonts
Font = pygame.font.SysFont("Trebuchet MS", 25)
#Day
DayFont = Font.render("Day:"+str(Day),1, Black)
DayFontR=DayFont.get_rect()
DayFontR.center=(985,20)
#Hour
HourFont = Font.render("Hour:"+str(Hour),1, Black)
HourFontR=HourFont.get_rect()
HourFontR.center=(1085,20)
#Minute
MinuteFont = Font.render("Minute:"+str(Minute),1, Black)
MinuteFontR=MinuteFont.get_rect()
MinuteFontR.center=(1200,20)
#Images
Timer=pygame.time.get_ticks
Clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(White)
#Timer
if Time<60:
time.sleep(1)
Minute=Minute+1
if Minute == 60:
Hour=Hour+1
Minute=0
if Hour==12:
Day=Day+1
Hour=0
if A1==0:
A1=A1+1
A2=A2+1
time.sleep(1)
if A1==1 or A2==1:
A2=A2-1
A1=A1-1
if A1==1:
screen.blit(MinuteFont, MinuteFontR)
screen.blit(HourFont, HourFontR)
screen.blit(DayFont, DayFontR)
if A2==0:
screen.fill(pygame.Color("White"), (1240, 0, 40, 40))
pygame.display.flip()
Clock.tick(60)
pygame.quit()
Sorry if this is nooby, but any help is appreciated
Barring all other problems, I'm not sure what your A1 and A2 are supposed to be, but
if A1==0: #true for the first run through
A1=A1+1 #A1 = 1
A2=A2+1
time.sleep(1)
if A1==1 or A2==1: #always true, since A1==1
A2=A2-1
A1=A1-1 #A1 = 0
this will always increase A1 and set it back to zero in the same step, essentially doing nothing, so you never get to the part if A1==1 where you might blit the time.
Apart from that, Font.render() "creates a new Surface with the specified text rendered on it." (cf. the documentation) This means you have to re-render the font every time you want to update the text, otherwise you keep blitting the same (unchanged) surface again and again. You will also need to adjust the rect to account for the text being wider then the time goes up from one digit to two.
The easiest way to keep track of time might be to use a custom user event that's fired every second in the event queue like so:
import pygame
pygame.init()
#Screen
size = width, height = 1280, 720 #Make sure background image is same size
screen = pygame.display.set_mode(size)
done = False
#Time Info
Time = 0
Minute = 0
Hour = 0
Day = 0
counter=0
#Colour
Black = (0,0,0)
White = (255, 255, 255)
#Fonts
Font = pygame.font.SysFont("Trebuchet MS", 25)
#Day
DayFont = Font.render("Day:{0:03}".format(Day),1, Black) #zero-pad day to 3 digits
DayFontR=DayFont.get_rect()
DayFontR.center=(985,20)
#Hour
HourFont = Font.render("Hour:{0:02}".format(Hour),1, Black) #zero-pad hours to 2 digits
HourFontR=HourFont.get_rect()
HourFontR.center=(1085,20)
#Minute
MinuteFont = Font.render("Minute:{0:02}".format(Minute),1, Black) #zero-pad minutes to 2 digits
MinuteFontR=MinuteFont.get_rect()
MinuteFontR.center=(1200,20)
Clock = pygame.time.Clock()
CLOCKTICK = pygame.USEREVENT+1
pygame.time.set_timer(CLOCKTICK, 1000) # fired once every second
screen.fill(White)
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == CLOCKTICK: # count up the clock
#Timer
Minute=Minute+1
if Minute == 60:
Hour=Hour+1
Minute=0
if Hour==12:
Day=Day+1
Hour=0
# redraw time
screen.fill(White)
MinuteFont = Font.render("Minute:{0:02}".format(Minute),1, Black)
screen.blit(MinuteFont, MinuteFontR)
HourFont = Font.render("Hour:{0:02}".format(Hour),1, Black)
screen.blit(HourFont, HourFontR)
DayFont = Font.render("Day:{0:03}".format(Day),1, Black)
screen.blit(DayFont, DayFontR)
pygame.display.flip()
Clock.tick(60) # ensures a maximum of 60 frames per second
pygame.quit()
I've zero-padded the minutes, hours and days so you don't have to recalculate the rectangle every time. You could also optimize the draw code by only drawing hours and days if they have changed (in the respective if statements).
To see other methods of how to handle timed events, check out Do something every x (milli)seconds in pygame.
Recently I've learned some basic Python, so I am writing a game using PyGame to enhance my programming skills.
In my game, I want to move an image of a monster every 3 seconds, at the same time I can aim it with my mouse and click the mouse to shoot it.
At the beginning I tried to use time.sleep(3), but it turned out that it pause the whole program, and I can't click to shoot the monster during the 3 seconds.
So do you have any solution for this?
Thanks in advance! :)
Finally I solved the problem with the help of you guys. Thank you so much!
Here is part of my code:
import random, pygame, time
x = 0
t = time.time()
while True:
screen = pygame.display.set_mode((1200,640))
screen.blit(bg,(0,0))
if time.time() > t + 3:
x = random.randrange(0,1050)
t = time.time()
screen.blit(angel,(x,150))
pygame.display.flip()
Pygame has a clock class that can be used instead of the python time module.
Here is an example usage:
clock = pygame.time.Clock()
time_counter = 0
while True:
time_counter = clock.tick()
if time_counter > 3000:
enemy.move()
time_counter = 0
I guess that works, but I feel think it would be more pythonic to do this.
import random, pygame
clock = pygame.time.Clock()
FPS = 26 #Or whatever number you want
loops_num = 0
while True:
screen = pygame.display.set_mode((1200,640))
screen.blit(bg,(0,0))
if loops_num % (FPS * 3) == 0:
enemy.move()
screen.blit(angel,(x,150))
pygame.display.flip()
loops_num += 1
clock.tick(FPS)
Or what Bartlomiej Lewandowski said, his answer is great also.