pygame: player fire delay - python

I want to have a delay between firing bullets for my character. I used to do this before in Java like:
if (System.currentTimeMillis() - lastFire < 500) {
return;
}
lastFire = System.currentTimeMillis();
bullets.add(...);
However, how can I do this in pygame way, in order to get that sys currentTimeMillis.This is how my run (game loop) method looks like:
time_passed = 0
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)
# time passed since game started
time_passed += clock.get_time()
As you can see in the previous code, I have created time passed, but I'm not sure if that is correct way of code order, and what else im missing.

Your code is fine, if game.process_events and game.update works as expected.
Edit:
Use pygame.time.get_ticks instead of the clock I mentioned earlier. It was using python's time module, so that clock and clock in your code meant different clocks. This is much better way.
#this should be done only once in your code *anywhere* before while loop starts
newtime=pygame.time.get_ticks()
# when you fire, inside while loop
# should be ideally inside update method
oldtime=newtime
newtime=pygame.time.get_ticks()
if newtime-oldtime<500: #in milliseconds
fire()
Let me explain you what pygame.time.get_ticks() returns:
On first call, it returns time since pygame.init()
On all later calls, it returns time (in milliseconds) from the first call to get_ticks.
So, we store the oldtime and substract it from newtime to get time diff.

Or, even simpler, you can use pygame.time.set_timer
Before your loop:
firing_event = pygame.USEREVENT + 1
pygame.time.set_timer(firing_event, 500)
Then, an event of type firing_event will be posted onto the queue every 500 milliseconds. You can use this event to signal when to fire.

Related

Is there a way to pause my if statement without pausing my entire script in pygame?

Pretty simple, I just want to make a damage system in pygame and i want invincibility frames (aka a delay) so that you don't just die instantly.
For reference here's the if statement
if pygame.Rect.colliderect(player_rect, baddude_rect):
print('hit')
time.sleep(0.5)
if you need the entire script i will post it, stackoverflow is picky.
I've already tried async and threading.
One way of doing this is to use the millisecond timer provided by pygame.time.get_ticks(). This returns the number of milliseconds since PyGame started. It's handy for doing time calculations.
So, reading through the comments, you want the player to be invulnerable for some time (0.5 seconds) after taking a hit. So let's get that into a constant:
HIT_CLOCK = 500 # milliseconds player is safe for, after taking a hit
So when the player is hit, we need to wait that long before recording another hit. This is some time in the future from when the player is hit, but that's easy to calculate:
time_now = pygame.time.get_ticks()
player_hit_clock = time_now + HIT_CLOCK # time in the future
And when the code is deciding if the player should be hit, it can just compare that "future time" to ensure it's now past:
if pygame.Rect.colliderect(player_rect, baddude_rect):
time_now = pygame.time.get_ticks()
if time_now > player_hit_clock:
print('hit')
player_hit_clock = time_now + HIT_CLOCK #<<-- reset clock
It's important to ensure player_hit_clock is initialised before the first use, setting it to 0 would be enough. So, putting all that together:
HIT_CLOCK = 500 # milliseconds player is safe for, after taking a hit
# ...
player_hit_clock = 0 # controls player consecutive damage rate
# ...
if pygame.Rect.colliderect(player_rect, baddude_rect):
time_now = pygame.time.get_ticks()
if time_now > player_hit_clock:
print('hit')
player_hit_clock = time_now + HIT_CLOCK # <<-- reset the hit-clock
else:
print('player hit cooldown')
The benefits of using the millisecond clock are:
All code just runs normally, waiting for the timer to expire.
The cost of using the clock is only a fetch of the time, with a single integer comparison.
(If you use the clock for other things, only one fetch is needed per loop)
It's real-time, so even if your program drops a few frames, timing is preserved.

python curses while loop and timeout

I am having a hard time understanding the window.timeout() function. To be more specific, I am toying with a "snake" game in python:
s = curses.initscr()
curses.curs_set(0)
w = curses.newwin()
w.timeout(100)
while True:
move snake until it hits the wall
I understand that in this case, timeout(100) determines how fast the snake "moves", i.e. printing out new characters on the screen. However, I got stuck when I want to amend the code so that it waits until someone press "start". I wrote something like:
w.timeout(100)
while True:
if w.getch() is not start:
stay at the initial screen
else:
while True:
move the snake until it hits the wall
However, in this case, the timeout(100) seems to govern how long each time the program waits for w.getch(), not how long to wait between each time the snake moves. Also, I notice that in the first example, the timeout is declared at the top, outside the while loop. This looks weird to me because normally if I want to pause a while loop, I would put sleep() at the bottom inside the while loop.
If you want to pause between snake moves, you could use napms to wait a given number of milliseconds (and unlike sleep, does not interfere with screen updates). Setting w.timeout to 100 (milliseconds) is probably too long. If you're not concerned with reading function-keys, you could use nodelay to set the w.getch to non-blocking, relying on the napms to slow down the loop.
Regarding the followup comment: in ncurses, the wtimeout function sets a property of the window named _delay, which acts within the getch function, ultimately passed to a timed-wait function that would return early if there's data to be read.

How to call periodically a function in Python turtle?

I have to code a game with turtle library.
In the rules, there is an object that fells every X milliseconds until a certain condition is reached.
If I use sleep(), the screen does not respond anymore to the keyboard events. Is there any way to periodically call a function "asynchronously" ?
Many thanks !
Python turtle provides a one-shot:
screen.ontimer(my_function, milliseconds)
which you can turn into an every X milliseconds timer event:
def my_function():
pass # do whatever
if still_needed: # start again in the future if still needed
screen.ontimer(my_function, 100) # repeat every 0.1 second

How do I pause code in an if function in pygame?

How do you make the code stop for a moment before checking for something else? (I'm new to code)
if BonusTime==True and Drop==True:
if event.type == pygame.MOUSEBUTTONDOWN:
window.blit(Fired,(mouseX-12,mouseY-12))
Cankill=True
#I want it to delay here
Cankill=False
There is a cross hair that follows the mouse and when I click it, it fires. The problem is, you can just hold the mouse down and leave the cross hair in one place. Whenever an enemy walks into the cross hair, they die. I need it so even when you hold it will only fire once. I plan to make it delay the if statement, to set "Cankill" to true and then wait a second, after waiting, it should set "Cankill" to false. I've already looked through a lot of other people's questions similar to this and haven't found something I can understand. So if you could please help me find out how to delay it in the way I need.
"Pausing" is not what you want - if you do that, your game will just freeze, and nothing will move (since you are usign the OS mouse pointer, maybe it could move).
Anyway, the function to "pause" inside a game is pygame.time.wait(1000) - the number is in miliseconds.
Waht you actually need is to mark down the time the click was made, continue with the game, and when 1 second has passed, reset the variable back to the other state.
Something along:
last_trigger = 0
while True:
# game updating code goes here (getting events, and such)
...
if Cankill and pygame.time.get_ticks() - last_trigger > 1000:
Cankill = False
if event.type == pygame.MOUSEBUTTONDOWN:
window.blit(Fired,(mouseX-12,mouseY-12))
Cankill=True
last_trigger = pygame.time.get_ticks()
The "get_ticks" call returns the number of miliseconds that passed since pygame was initialized - and is usefull for this time of timers.

Trying to add a timer to my game

This is a really simple question, and I don't know why I haven't got the answer to it, but does anyone know how to correctly add a timer in pygame for Python 3.4.1?
Here's what I have so far:
texta = font.render("Time:"+str(time), True, black)
screen.blit(texta, [500,100])
I have read solutions using loops and many others, but none have worked so far. I want a timer to be displayed on the screen and count the seconds it takes for the user to perform a certain task.
Here is a timer you can use
import pygame, sys
from pygame.locals import *
clock = pygame.time.Clock()
time = 0 #In Seconds
#GameLoop
while True:
milli = clock.tick() #clock.tick() returns how many milliseconds passed since the last time it was called
#So it tells you how long the while loop took
seconds = milli/1000.
time += seconds
print time #So you can see that this works
You can use jues velarde's code above and just print the time variable onto to your pygame surface using
font = pygame.font.Font(YourFont, YourSizeOfText)
text = font.render(str(time), 1, (YourColour)) # The time variable being in jues's code
DISPLAYSURF.blit(text, (YourXValue, YourYValue)
and you would just call this code in a loop when you want too, in your case, when you want to begin timing the user's task, But remember to run jues's code in your program as well so this will work.
Hope i helped!

Categories

Resources