I am fairly new to PyGame and I am creating a space shooter game. Part of this game are powerups and when a specific powerup is picked up by the player, I want the player not to be able to shoot for 3 seconds. Shooting is done by mouse click.
I can pick up the powerup, I know what powerup the player last picked up, but I am struggling with the event. How I am thinking of implementing is:
Can't Shoot power up is picked up -> that's done
Block mouse buttons
Wait 3 seconds, while the rest of the game is still running
Unblock mouse buttons.
I am aware that Python functions, such as wait, won't help.
Any ideas/suggestions?
Thanks
When you call clock.tick() it returns time since the last call. So save that time: dt = clock.tick() and then use that variable to count down your seconds.
Example:
dt = clock.tick() # only call once per iteration
if attack_blocked:
attack_block_count += dt
if attack_block_count >= 3000: # dt is in ms
attack_blocked = False
Example 2:
while True:
dt = clock.tick(60)
for event....
if block_attack_power_up:
attack_blocked = True
attack_block_count = 0
if not attack_blocked:
# do your attack
if attack_blocked:
attack_block_count += dt
if attack_block_count >= 3000:
attack_blocked = False
Related
I'm trying to get a series of lines to fall through the screen at exact tempo, for example, you input say 120 BPM and the result is the road lines hitting the bottom of the screen at 120 BPM.
I have tried using both pygame.clock.tick() and pygame.time.delay() (which I heard is more accurate), however when I use these as a clock to blit both the background and the road lines, against a metronome the clock seems very inconsistent.
For making an exact rhythm game which must stay in time for the entire song, is there another way to do this?
#GAMELOOP
while playing==True:
win.blit(bg,(0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
playing = False
#win.fill(WHITE)
y1=y1+gameSpeed
y2=y2+gameSpeed
y3=y3+gameSpeed
win.blit(track1,(x,y1))
win.blit(track2,(x,y2))
win.blit(track3,(x,y3))
if y1>=1000:
y1=-2000
if y2>=1000:
y2=-2000
if y3>=1000:
y3=-2000
fpsClock.tick(30)
pygame.display.update()
pygame.quit()
120 BPM (which I assume is "Beats Per Minute"), is only a per half-second timing, that's reasonably slow in computer terms. Most applications repaint the screen at 3600 frame-updates per minute (60Hz).
You can use the pygame.time object to return the number of milliseconds since the program started. This is really useful for timing things in the game:
clock = pygame.time.get_ticks() # time now
So immediately on start-up, this time is "0 milliseconds", and grows from there, forever more.
This value can then be used in relative time comparisons. When you make the track1 fall, it's possible to update the y-position based on the clock. One way to do this is to calculate the future millisecond-time at which the track1 should next move:
clock = pygame.time.get_ticks()
track1_move_next_time = clock + 500 # 500 milliseconds = 120 BPM
The repeatedly check that time until it's in the past. Then move the track1:
# In the Main Loop:
clock = pygame.time.get_ticks()
# ...
if ( clock > track1_move_next_time ): # is it time to move?
y1 += pixels_per_tick # move it
track1_move_next_time = clock + 500 # set next move time
I'm trying to do a chess clock using tkinter, and to do so i'm using the root.after method from the class Tk of tkinter. When the program starts, it runs really well, but after a while the clock start to get slower and slower, but if i start shaking my mouse, the clock starts to run fast again. For a clock, time precision is crucial, so i can't afford to run the program in the way that is working now. How can i solve this problem?
def RunClock(self):
"""
Method that runs and change the clock info
"""
#t0 = time.time()
if self.playing:
#Time remaining in milliseconds
clock = self.clock
minutes = clock//60000
clock %= 60000
sec = clock//1000
clock %= 1000
mil = clock//10
#If the turn is of player 1
if self.turn == 1:
self.WriteClock(self.canvas1, self.play1, "%.2i:%.2i:%.2i"%(minutes, sec, mil))
else:
self.WriteClock(self.canvas2, self.play2, "%.2i:%.2i:%.2i"%(minutes, sec, mil))
#tf = time.time()
#deltat = (tf - t0)
#s = 1 - deltat
self.rel -= 1
#if s > 0:
# time.sleep(s/1000)
#else:
# self.rel += s*1000
self.root.after(1, self.RunClock)
Note: The time to run the function is very low (you can calculate it with the commented tf and t0 variables), so i didn't even consider it in the time interval
As Brian pointed out reducing the time interval will likely be the easiest solve to your question. Alternately though, you could try running your timer separately on it's own thread and having it run asynchronously and send it threading events as is discussed here:
Python threading.timer - repeat function every 'n' seconds
I so far have a game that runs at 60 fps,but i need the character to have a animation for when he is walking. I have looked at sources for days but have come up empty on how to make this time based loop work. If you could create a example and explain how it works i would be so thankful!
Change animation every 1 second (1000ms) - using pygame ticks.
current_time = pygame.time.get_ticks()
next_move = current_time + 1000 # 1s = 1000ms
# mainloop
while True:
current_time = pygame.time.get_ticks()
if next_move <= current_time:
change_animation()
next_move = current_time + 1000
This code not depends on FPS.
I am building a space invaders style game in Pygame. The enemies come in one at a time, and each loop sounds associated with them (this is for a psychology experiment in auditory learning, actually)
I want to put a 5 second delay in the game after a character is killed--so, when one character is shot, their sound fades out quickly, and the player must wait 5 seconds for the onset of the next character + sound
This is the script I have within my Game class, for generating enemies one at a time. I am using the core module from psychopy to measure time, but I can't seem to figure out how to delay the enemy onset without freezing the game (i.e. still allowing the player to move between onsets):
if len(self.enemyA_list) == 0 and len(self.enemyB_list) == 0 and len(self.enemyC_list) == 0:
self.enemy = Enemy()
#Increase speed, variability of character onset based on how many characters have been created
if len(self.dead_enemies) == 2 or len(self.dead_enemies) == 3:
self.enemy.x_speed *= 1.75
self.enemy.y_speed *= 1.75
elif len(self.dead_enemies) == 4:
self.enemy.x_speed *= 2
self.enemy.y_speed *= 2
timer = core.Clock()
timer.add(2)
if timer.getTime()>=0:
timer = 0
self.enemy.generate() #generate enemy offscreen and start playing sound
if self.enemy.enemy_type == 'A':
self.enemyA_list.add(self.enemy)
self.enemy.sound.out() #play enemy sound
self.enemy.env.play()
if self.enemy.enemy_type == 'B':
self.enemyB_list.add(self.enemy)
self.enemy.sound.out()
self.enemy.env.play()
if self.enemy.enemy_type == 'C':
self.enemyC_list.add(self.enemy)
self.enemy.sound.out()
self.enemy.env.play()
self.all_sprites_list.add(self.enemy)
In your main game loop you should just create a variable keeping track of how much time there has been since the last spawn.
Declare a variable.
lastTime = 0
Then you add 1 to lastTime each time through the loop.
lastTime += 1
Then you need to check how long it's been since the last time one spawned. Also you need to decide how many seconds you want between the spawns.
So...
if timeElapsed == FPS * secondsBetweenSpawns:
generateEnemy()
This will delay each spawn. Please note that this will require an FPS and an FPSClock.
In my pong game, whenever someone scores (the ball goes out to the left or to the right) the ball position is reset to the middle of screen and it waits one second before moving. In that one second I have a little animation going on.
My problem is this: if I pause the game in the middle of the animation, even though none of the objects are updated and only the pause text is drawn, time keeps rolling in. And if I wait time enough, the animation just stops right after I unpause the game. Here's what I mean. This is the ball update:
def update(self, dt):
now = pygame.time.get_ticks() / 1000
# if time elapsed since the ball got out >= BALL_WAIT_TIME
if now - self._spawn_time >= BALL_WAIT_TIME:
self.rect = self.calcnewpos(dt)
self.handle_collision()
# spawn animation
else:
step = 255 / (FPS * BALL_WAIT_TIME)
value = int(self._frame * step)
rgb = (value, value, value)
self._draw_ball(rgb)
self._frame += 1
From http://pygame.org/docs/ref/time.html#pygame.time.get_ticks:
pygame.time.get_ticks()
Return the number of millisconds since pygame.init() was called. Before pygame is initialized this will always be 0.
So even though nothing is drawn or updated while the game is paused, pygame.time.get_ticks() will still return the time elapsed since pygame.init. How can I solve this? Sorry if that is a little hard to understand, I'll post the rest of the code if needed.
Well it looks as though you're just subtracting the time that some event occurred from the current time. If that's your method for checking how much time has elapsed since the event, then it's not going to matter if the game has been paused. If the event happens and you then pause the game for 10 minutes, it's always going to have been 10 minutes since the event happened.
So with that in mind, you need some way to only count time when the game is active. Perhaps the ball could have an attribute that says how long since the ball got out, and you only increase it if the game isn't paused.
Edit: something like:
class Ball:
def spawn(self):
self.sinceSpawn = 0
def update(self, dt):
if not gamePaused:
self.sinceSpawn += dt
if self.sinceSpawn >= BALL_WAIT_TIME:
pass #Do something here