How can i make time based loop in pygame - python

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.

Related

Is there a more accurate clock for pygame for a rhythm game I'm making

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

Pygame - Run event for 3 seconds only once

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

Python Tkinter Tk root.after Delay

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

How can I add a timer to my game?

I'm working on a game that is sort of like a simple Galaga-esk game. Although, they only move once in a while (something else I can't get working, but that's something different). So, since they don't move on their own, I want a way to add a timer to the game, but I can't seem to find anything on this. Here's what I have for my timer and the surrounding code to reset for each level so far. Will something like this work where I have it?
from livewires import games, color, random, time
start = time.time()
for items in enemies:
items.destroy()
if Enemy_amount > 0:
display_balloons()
elif Enemy_amount == 0 and (time.time() - start <= 120):
start = time.time()
level += 1
Enemy_amount = load_enemies()
#Just telling the code to load the next group of enemies.
The value of start is going to be a number like 1398354442, which is the number of seconds that have passed since January 1, 1970.
If you want to figure out the elapsed time between two events, you'll need to subtract. Perhaps something like this?
elif Enemy_amount == 0 and (time.time() - start <= 120):
start = time.time() # update start variable to the current time

How to make an object have temporary invincibility?

I'm making a game in pygame and I need my ship to be immune for, about, 3 seconds after a collision with an asteroid. I tried every function I found, but it didn't work.
Here's the collision part of my code:
if collision == True:
ship_game = ship_destroyed
lifes -= 1;
And then i have this part:
if collision:
pi = True
collision = False
pygame.time.delay(1000)
This variable called pi I use in case of collision to put the ship in the middle of screen:
if pi == True:
ship_game = ship
pos_ship={'x': WScreen/2, 'y': HScreen/2}
pi = False
I think that's enough for you to understand my problem. Thank you :)
This could be accomplished by introducing a variable collision_immune that you set to True when a collision is detected. At the same time you record the time of the last collision in a variable collision_time. You can get the time from pygame.time.get_ticks(). Then in an appropriate part of your main loop, that is not shown above, you can check if the time since the last collision is more than, say, 3 seconds and reset collision_immune to False. This could look something like this
if collision == True:
ship_game = ship_destroyed
lifes -= 1;
collision_immune = True
collision_time = pygame.time.get_ticks()
Then somewhere, maybe at the beginning of the main loop, you put
if pygame.time.get_ticks() - collision_time > 3000: # The time is in ms.
collision_immune = False
Now you can use the variable collision_immune in your game logic to determine if the ship is immune from a recent collision.
Happy pygaming! :)
You need to keep track of the time when the last collision took place (last_collision_time = time.time()) and then when a collision happens you check if that value is less than 3 seconds ago (if time.time() - last_collision_time < 3.:) and handle it as you see fit. In this case clearly by not having the collision destroy the ship.
OOP style:
class Ship:
def immune(self):
return self.last_collide_time > current_time() - 3000
def collide(self):
if self.immune(): return
self.lifes -= 1
self.last_collide_time = current_time()
# ....

Categories