I'm currently programming a brick-breaker clone using the Pyglet library and I would like to make a timer that counts up to 20 seconds for the game's 'bonuses'(i.e. longer paddle, faster paddle movement, a larger ball). I've been digging the internet as hard as I can but I couldn't find the answer.
import threading
bonuses_count = 0
def count_bonuses():
global bonuses_count
# paddle = count(paddle) # something your logic part here
bonuses_count += 20
print "counting bonuses :- ", (bonuses_count)
t = threading.Timer(20.0, count_bonuses).start()
t = threading.Timer(20.0, count_bonuses)
t.start()
Well i don't know your logic of counting bonuses but i think you can acheive 20 seconds timer by creating a thread which will executing after every 20 seconds.
Here i have created function count_bonuses that will contain your game logic and get executed after every 20 seconds.
You can create your own stopflag if you want to stop this thread or create an KeyboardInterrupt to stop the thread with keyboard intruption based on your gamming logic.
counting bonuses :- 20
counting bonuses :- 40
counting bonuses :- 60
counting bonuses :- 80
Try this.
import mx.DateTime as mt
import time
def settime():
st=mt.now()
while(True):
time.sleep(1)
tt=mt.now()
if (int((tt-st).seconds)==20):
print 'level up'
st=mt.now()
elif (int((tt-st).seconds)>20):
print 'logic error'
else:
print int((tt-st).seconds)
Related
I am learning python, and am trying to make (how original) a disease model, where green balls bounce around and if a red ball touches them, they get infected with the red color.
I am trying to make it so every x seconds, each infected red ball has a probability to die and turn black, but I can't figure out how to do that. I have tried to use pygame's clocks but couldn't figure it out.
here's the die function
def die(particle_list):
for i in particle_list:
if (i.colour == red) and random.choice([1,1,1,1,1,1,1,1,1,1,1,1,1,1,0])==0:
i.colour = black
If the task of checking the red balls for killing them is suppose to happen without bothering the rest of the process, then I'd suggest that you use a separate thread to check it and perform operation.
Check out the threading module in standard library for examples.
Simplest example would be:
import threading, time
def checkballs_and_turn_black(balls_data):
while True:
time.sleep(10) # sleep for 10 secs
for ball in balls_data:
if check_probability(ball):
ball.set_black()
t = threading.Thread(target=checkballs_and_turn_black, args=(actual_balls_data,))
t.start()
Use the time.sleep method. It will block program execution for the given number of seconds.
I would also like to point out that is better to use random numbers for probablilities like this. In you example your particle has a 1 in 15 chance to die, so you would want to generate a random number from 0 to 1, and i the number is bellow 0.066666667 (1 / 15) the particle will die.
This example will do what you want:
import random
def die(particle_list, death_rate):
for particle in particle_list:
if random.random() <= death_rate:
particle.color = black
I have now solved the issue. I didn't yet firgure out how multithreading works, but I will look into tutorials for that as that seems easier than what I came up with. I did this:
d = 0
def day_counter():
global day_count, timelist
time = int(pg.time.get_ticks()/1000)
if time not in timelist:
timelist.append(time)
d = True
if timelist[-1]%(seconds_in_a_day) == 0 and d:
day_count += 1
d = False
e = True
so that the constant e becomes True every in-game day (which ticks every (seconds_in_a_day) seconds) Then, I used the constant e to regulate how often the other time based functions happen, like this:
def die(particle_list):
global sick_count,dead_count,e
for i in particle_list:
if i.colour == red and e:
if r.random() < death_rate:
i.colour = black
sick_count -= 1
dead_count += 1
e = False
Answer added on behalf of OP.
I need to call a function, exactly 08:00, 18:00, 22:00 hours. I've created a example to test the comparison between hours. When the current time reaches one of those horary. Put in inside a While loop thinking this example would work as a stopwatch, but I think I'm wrong. How is the best way to compare those values?
currentH= dt.datetime.now().strftime("%H:%M:%S")
h = "16:15:10"
while True:
if(currentH==h):
print 'Ok'
print 'The current Hour is: '+h
import datetime as dt
import time
currentH= dt.datetime.now().replace(microsecond=0).time()
hrs = ['00:02', '12:00']
for i in range(len(hrs)):
h = [int(x) for x in hrs[i].split(':')]
h = dt.datetime.now().replace(hour=h[0], minute=h[1], second=0,microsecond=0).time()
hrs[i] = h
while True:
currentH = dt.datetime.now().replace(microsecond=0).time()
print(currentH)
if currentH in hrs:
print('Time is now',currentH)
time.sleep(1)
The biggest problem with your code is that you never call now() again inside the loop, so you're just spinning forever comparing the initial time to 16:15:10.
While we're at it: Why convert the time to a string for comparison instead of just comparing times?
But there are bigger problems with this design that can't be fixed as easily.
What happens if you check the time at 16:15, then go to sleep, then wake up at 16:25? Then now() never returns 16:15:10.
Also, do you really want to burn 100% CPU for 10 hours?
A better solution is to write a sleep_until function:
def sleep_until(target):
left = target - dt.datetime.now()
if left > dt.timedelta(seconds=0):
time.sleep(left.total_seconds())
(If you're using Python 2.7 or 3.4, it's a bit more complicated, because sleep will wake up early if there's a signal. But to handle that case, you just need to add a while True: loop around the whole thing.)
Now, the only tricky bit is working out the first time you need to sleep until, which isn't all that tricky:
waits = itertools.cycle(dt.timedelta(hours=wait) for wait in (10, 4, 10))
now = dt.datetime.now()
start = dt.datetime.combine(dt.date.today(), dt.time(hour=8))
for wait in waits:
start += wait
if start > now:
break
And now, we just loop over the waits forever, sleeping until each next time:
for wait in waits:
sleep_until(start)
print('Time to make the donuts')
start += wait
Or, of course, you could just grab one of the many scheduling libraries off PyPI.
Or just use your platform's cron/launchd/Scheduled Tasks API to run your script.
having issues trying to get threading working in python using the awesome Appjar package.
The following program needs to count through a list, and update a progress bar simultaneously. I've followed the appjar documentation for threading, but it's returning NameError: name 'percent_complete' is not defined in the app.thread (line 35), in which you're meant to insert function params - my code is below:
from appJar import gui
import time
# define method the counts through a list of numbers, and updates the progress meter
def press(btn):
objects = [1,3,6]
total = len(objects)
current_object = 0
for i in objects:
print(i)
current_object += 1
current_percent_complete = (current_object / total) * 100
updateMeter(current_percent_complete)
time.sleep(1)
def updateMeter(percent_complete):
app.queueFunction(app.setMeter, "progress", percent_complete)
# create a GUI variable called app
app = gui("Login Window")
app.setBg("orange")
app.setFont(18)
# add GUI elements : a label, a meter, & a button
app.addLabel("title", "COUNTER")
app.setLabelBg("title", "blue")
app.setLabelFg("title", "orange")
app.addMeter("progress")
app.setMeterFill("progress", "green")
app.addButton("START COUNTING", press)
# put the updateMeter function in its own thread
app.thread(updateMeter, percent_complete)
# start the GUI
app.go()
I can get rid of the error by defining percent_complete like so:
from appJar import gui
import time
# define method the counts through a list of numbers, and updates the progress meter
percent_complete = 0
def press(btn):
...
However, when GUI loads and button is pressed it doesn't thread. Instead it iterates through the list, then updates the progress bar afterwards.
Has anyone come across the same issue? any insight would be awesomely appreciated!
Thanks!
There are a couple of issues here:
First, I'm not sure your maths result in good percentages to update the meter with, so you might not see much change - should you be using i?
Second, the GUI won't be updated until the loop (and the sleeps inside it) all complete. Instead, you should try counting how many items to process, and iterating through them with an after() function, see here: http://appjar.info/pythonLoopsAndSleeps/#conditional-loops
Third, the call to app.thread() at the end doesn't achieve much - it calls the update_meter() function with a parameter that doesn't exist, it can be removed.
Fourth, the actual update_meter() function isn't necessary, as you're not really using a thread - that can be removed as well...
Give this a try, once you've had a look at the maths:
current_object = 0
def press(btn):
global current_object
current_object = 0
processList()
def processList():
global current_object
objects = [1,3,6]
total = len(objects)
if current_object < total:
i = objects[current_object]
print(i)
current_object += 1
current_percent_complete = (current_object / total) * 100
app.setMeter("progress", current_percent_complete)
app.after(1000, processList)
UPDATE: just to clarify on the maths issue, you're dividing one integer by another: 0/3, 1/3, 2/3, 3/3 and so on. In python2 this will result in 0, in python3 you'll get fractions.
In an MMO game client, I need to create a loop that will loop 30 times in 30 seconds (1 time every second).
To my greatest disappointment, I discovered that I can not use time.sleep() inside the loop because that causes the game to freeze during the loop.
The loop itself is pretty simple and the only difficulty is how to delay it.
limit = 31
while limit > 0 :
print "%s seconds remaining" % (limit)
limit = limit -1
The python libs exist in the client as .pyc files in a separate folder and I'm hoping that I can avoid messing with them.
Do you think that there is any way to accomplish this delay or is it a dead end?
Your game has a main loop. (Yes, it does.)
Each time through the loop when you go to check state, move the players, redraw the screen, etc., you check the time left on your timer. If at least 1 second has elapsed, you print out your "seconds remaining" quip. If At least 30 seconds has elapsed, you trigger whatever your action is.
You can't do it without blocking or threading unless you are willing to lose precision...
I'd suggest sometime like this, but threading is the correct way to do this...
import time
counter = 31
start = time.time()
while True:
### Do other stuff, it won't be blocked
time.sleep(0.1)
print "looping..."
### When 1 sec or more has elapsed...
if time.time() - start > 1:
start = time.time()
counter = counter - 1
### This will be updated once per second
print "%s seconds remaining" % counter
### Countdown finished, ending loop
if counter <= 0:
break
or even...
import time
max = 31
start = time.time()
while True:
### Do other stuff, it won't be blocked
time.sleep(0.1)
print "looping..."
### This will be updated every loop
remaining = max + start - time.time()
print "%s seconds remaining" % int(remaining)
### Countdown finished, ending loop
if remaining <= 0:
break
I have created a simple score system for my pygame. but it's pausing the game. I know it's because of time.sleep but I don't how to sort it out.
The score system is to +100 every 5 seconds while start is true, code:
while start == True:
time.sleep(5)
score = score + 100
Full code with indentation: http://pastebin.com/QLd3YTdJ
code at line : 156-158
Thank you
Instead of using sleep, which stalls the game until time has elapsed, you want to count up an internal timer with the number of seconds which have passed. When you hit 5 seconds, increment the score and then reset the timer.
Something like this:
scoreIncrementTimer = 0
lastFrameTicks = pygame.time.get_ticks()
while start == True:
thisFrameTicks = pygame.time.get_ticks()
ticksSinceLastFrame = thisFrameTicks - lastFrameTicks
lastFrameTicks = thisFrameTicks
scoreIncrementTimer = scoreIncrementTimer + ticksSinceLastFrame
if scoreIncrementTimer > 5000:
score = score + 100
scoreIncrementTimer = 0
This could easily be improved (what if your frame rate is so low there's more than 5 seconds between frames?) but is the general idea. This is commonly called a "delta time" game timer implementation.
If i understand you correctly you dont want the while True: score += 100 loop to block your entire program?
You should solve it by moving the score adding to a seperate function
and use the intervalfunction of APScheduler http://packages.python.org/APScheduler/intervalschedule.html
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.start()
# Schedule job_function to be called every 5 seconds
#sched.interval_schedule(seconds=5)
def incr_score():
score += 100
This will result in APScheduler creating a thread for you running the function every 5 seconds.
you might need to do some changes to the function to make it work but it should get you started at least :).