As you can see in the below code I have a basic timer system
done = False
clock = pygame.time.Clock()
# Create an instance of the Game class
game = space_world.SpaceWorld()
# Main game loop
while not done:
# Process events (keystrokes, mouse clicks, etc)
done = game.process_events()
# Update object positions, check for collisions...
game.update()
# Render the current frame
game.render(screen)
# Pause for the next frame
clock.tick(30)
My question is, how can I get the current time milli seconds and how do I create delta time, so I can use it in the update method ?
ms = clock.tick(30)
The function returns milliseconds since the previous call.
From the documentation: pygame.time.Clock.get_time will return the number of milliseconds between the previous two calls to Clock.tick.
There is also pygame.time.get_ticks which will return the number of milliseconds since pygame.init() was called.
Delta-time is simply the amount of time that passed since the last frame, something like:
t = pygame.time.get_ticks()
# deltaTime in seconds.
deltaTime = (t - getTicksLastFrame) / 1000.0
getTicksLastFrame = t
Related
I am trying to get objects spawn on screen. But they don't seem to come up.
When exiting the game the sprites come up. It's only during the game you can't see any objects.
Exit = False
while not Exit:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == QUIT:
Exit = True
elif event.type == USEREVENT +1:
fireball.add(fire(screen, random.randint(50,1000), random.randint(50,800)))
fireball.update()
fireball.draw(screen)
pygame.display.flip()
Since you do not tell us, I'm going to assume that fireball is a sprite.Group and fire a child class of sprite.Sprite. From the little I can see, seems to be the correct guess.
So what you want is to create and add fire instances to the fireball group during the game.
You can achieve it by adding the following lines in the main loop before firefall.update():
newev = pygame.event.Event(USEREVENT+1)
pygame.event.post(newev)
This will create a custom event of type USEREVENT+1 which will be catch by the event checking loop next iteration, executing hence the line: fireball.add(fire(screen, random.randint(50,1000), random.randint(50,800)))
Maybe you do not want to create a new fire sprite each iteration. In that case you should add some flow control to skip those lines under some conditions.
For example, if you want a random approach, you can do:
if random.random() < 0.1:
newev = pygame.event.Event(USEREVENT+1)
pygame.event.post(newev)
In this case, each iteration of the main loop you have a 10% of probability to submit the custom event. Adjust the probability to your suits.
If instead you want to add a new fire sprite after a given amount of time, you need to measure the time with pygame.time.get_ticks(). If a given amount of time is passed, the event is submitted.
checktime = pygame.time.get_ticks() - reftime
if checktime > 5000: #5 seconds, the time is in milliseconds
reftime = pygame.time.get_ticks() #reset the reference time
newev = pygame.event.Event(USEREVENT+1)
pygame.event.post(newev)
And of course remember to define reftime = pygame.time.get_ticks() the first time before the main loop.
You can refer to this answer for another example on how to measure time with pygame.
I am making this game where you use the w, a, s, d keys to move a ball. I am trying to make a timer that starts when you press "start game". The problem is, when I do something like time.sleep, it interrupts the movement of the ball. I want to render the timer in the top right corner of the screen and make it 1 minute (also I will make a conditional statement for when the timer stops so I would like that to be possible).
This is what I believe would be easiest, and fit your needs the best.
clock = pygame.time.Clock()
fps = 60 # Or whatever frame-rate you want to cap the game at.
time = 0
game_started = False
# This is the main loop.
while True:
dt = clock.tick(fps)
if game_started:
time += dt
if time >= 60000: # 60 seconds.
game_started = False
# Then handle, events, update/draw objects etc.
Just set game_started = True when you press the button and the time variable will start to increment in time. Then you can just draw the time variable to the screen however you like. If you don't want to draw it when it isn't running then just blit it when game_started is True.
I created this function that randomly spawn a dot, but because its in my game loop the dot just does not stay where it is. I want it to spawn a dot and then wait 6 seconds and spawn another one randomly, but the first still being there. Because there is other things happening on the screen at the same time I cant use time.sleep(6). Any help solving this would be really appreciated.
def random_spawn():
image_x = random.randrange(122, 476)
image_y = random.randrange(90, 350)
screen.blit(Green, (image_x, image_y))
Don't use time.sleep. In general, in game programming, you never want to use time.sleep for any reason.
In your case, you just need to check a timer or clock every so often, and if the time is up, run your spawn function.
This is what a typical game loop will look like:
while True:
# get/handle player input
# update game state
# update sprites
# draw background
# draw sprites
# flip display
In your case, when you update your game state, you should check how much time has passed since you last spawned your random sprite. If it has been longer than 6 seconds, spawn a new one.
It will look something like this:
if time.clock() - last_spawn_time > 6.0:
random_spawn()
I think a way to fix this would be to only randomly spawn a dot if certain conditions are met. So you can define a function that randomly generates new coordinates outside of your main function (and returns them). Then your main game loop will take care of rendering the dot on the screen if certain conditions are met. For example:
image_x, image_y = get_random_coordinates()
while True:
if time.clock() - last_spawn_time > 6.0:
image_x, image_y = get_random_coordinates()
last_spawn_time = time.clock()
screen.blit(Green, (image_x, image_y))
So the idea is that you draw the same random coordinates, and keep drawing those same coordinates until the time between your last spawning and now is more than 6 seconds.
If you are trying to avoid using threads, and just using a while loop, perhaps this might work:
import time
def my_function():
print 'it has been about 6 seconds'
prev_time_stamp = time.time()
while True:
#do something
#do something else
if time.time() > prev_time_stamp + 6:
prev_time_stamp = time.time()
my_function()
#do something else
import random module:
import random
create random coordinates:
rand_X = (random.randrange(0, display_width - image_width)
rand_Y = (random.randrange(0, display_height - image_height)
blit image:
gameDisplay.blit(yourimage,(randAppleX,randAppleY))
I'm learing Python and Pygame, and my first thing I'm making is a simple Snake game. I'm trying to make it so that the snake moves once every 0.25 seconds. Here is the part of my code that loops:
while True:
check_for_quit()
clear_screen()
draw_snake()
draw_food()
check_for_direction_change()
move_snake() #How do I make it so that this loop runs at normal speed, but move_snake() only executes once every 0.25 seconds?
pygame.display.update()
I want all of the other function to run normally, but move_snake() to only occur once every 0.25 seconds. I've looked it up and found a few answers but they all seem too complicated for someone who's making their first ever Python script.
Would it be possible to actually get an example of what my code should look like rather than just telling me which function I need to use? Thanks!
There are several approaches, like keeping track of the system time or using a Clock and counting ticks.
But the simplest way is to use the event queue and creating an event every x ms, using pygame.time.set_timer():
pygame.time.set_timer()
repeatedly create an event on the event queue
set_timer(eventid, milliseconds) -> None
Set an event type to appear on the event queue every given number of milliseconds. The first event will not appear until the amount of time has passed.
Every event type can have a separate timer attached to it. It is best to use the value between pygame.USEREVENT and pygame.NUMEVENTS.
To disable the timer for an event, set the milliseconds argument to 0.
Here's a small, running example where the snake moves every 250 ms:
import pygame
pygame.init()
screen = pygame.display.set_mode((300, 300))
player, dir, size = pygame.Rect(100,100,20,20), (0, 0), 20
MOVEEVENT, t, trail = pygame.USEREVENT+1, 250, []
pygame.time.set_timer(MOVEEVENT, t)
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_w]: dir = 0, -1
if keys[pygame.K_a]: dir = -1, 0
if keys[pygame.K_s]: dir = 0, 1
if keys[pygame.K_d]: dir = 1, 0
if pygame.event.get(pygame.QUIT): break
for e in pygame.event.get():
if e.type == MOVEEVENT: # is called every 't' milliseconds
trail.append(player.inflate((-10, -10)))
trail = trail[-5:]
player.move_ip(*[v*size for v in dir])
screen.fill((0,120,0))
for t in trail:
pygame.draw.rect(screen, (255,0,0), t)
pygame.draw.rect(screen, (255,0,0), player)
pygame.display.flip()
Use the Clock module of Pygame to keep track of time. Specifically the method tick of the Clock class will report to you the number of milliseconds since the last time you called tick. Therefore you can call tick once at the beginning (or at the end) of every iteration in your game loop and store its return value in a variable called dt. Then use dt to update your time-dependent game state variables.
time_elapsed_since_last_action = 0
clock = pygame.time.Clock()
while True: # game loop
# the following method returns the time since its last call in milliseconds
# it is good practice to store it in a variable called 'dt'
dt = clock.tick()
time_elapsed_since_last_action += dt
# dt is measured in milliseconds, therefore 250 ms = 0.25 seconds
if time_elapsed_since_last_action > 250:
snake.action() # move the snake here
time_elapsed_since_last_action = 0 # reset it to 0 so you can count again
I'm trying to write a python game loop that hopefully takes into account FPS. What is the correct way to call the loop? Some of the possibilities I've considered are below. I'm trying not to use a library like pygame.
1.
while True:
mainLoop()
2.
def mainLoop():
# run some game code
time.sleep(Interval)
mainLoop()
3.
def mainLoop():
# run some game code
threading.timer(Interval, mainLoop).start()
4.
Use sched.scheduler?
If I understood correctly you want to base your game logic on a time delta.
Try getting a time delta between every frame and then have your objects move with respect to that time delta.
import time
while True:
# dt is the time delta in seconds (float).
currentTime = time.time()
dt = currentTime - lastFrameTime
lastFrameTime = currentTime
game_logic(dt)
def game_logic(dt):
# Where speed might be a vector. E.g speed.x = 1 means
# you will move by 1 unit per second on x's direction.
plane.position += speed * dt;
If you also want to limit your frames per second, an easy way would be sleeping the appropriate amount of time after every update.
FPS = 60
while True:
sleepTime = 1./FPS - (currentTime - lastFrameTime)
if sleepTime > 0:
time.sleep(sleepTime)
Be aware thought that this will only work if your hardware is more than fast enough for your game. For more information about game loops check this.
PS) Sorry for the Javaish variable names... Just took a break from some Java coding.