6

I would like to add 1 to a variable every minute without interfering with the code that's already running.

It is a game so I want in the background for wood+1, rock+1, fish+1 to happen every minute without the user knowing.

the time.sleep won't work in this situation because it pauses the whole program.

start=time.time()
#some code
end=time.time()
if end-start > 60:
    wood = wood+1
    rock = rock+1

I tried doing something above but could not get it to continuously count. It only measures how long it takes for #some code to be executed.

Any help would be great! Thanks in advance.

karthikr
  • 97,368
  • 26
  • 197
  • 188
MahoreLee
  • 143
  • 1
  • 3
  • 12
  • related: [Python Equivalent of setInterval()?](http://stackoverflow.com/q/2697039/4279) – jfs Mar 20 '14 at 09:54

4 Answers4

9

You need to import the thread module and the itertools (in addition to svks' comment) in python

import thread, time, itertools

initialize your threadsafe counter like

wood = itertools.count().next()

and write your counter update into a function

def updateCounter():
   while True:
       wood.next()
       # wood += 1
       time.sleep(60)

and kick off a new thread with

thread.start_new_thread(updateCounter, ())

But the ressource variables like wood must be accessable from within the counter function!

Community
  • 1
  • 1
thomas
  • 2,580
  • 1
  • 22
  • 28
  • You could possibly make the resources globals, but globals are always a bad idea. – Rushy Panchal Apr 03 '13 at 18:53
  • This is not thread safe ( x += 1 is not atomic: http://29a.ch/2009/2/20/atomic-get-and-increment-in-python ). If you do this and you elsewhere in the game do wood -= 100, you might on occasion find that one of the changes is mysteriously lost. – svk Apr 03 '13 at 18:53
  • But now wood is a counter. I sort of assumed it was meant to be a self-refreshing resource that could be consumed in other threads. I don't think you can get around using a lock if you want to use threads here. – svk Apr 03 '13 at 19:08
  • 2
    Don't use `thread` module directly, use `threading` module instead: `Thread(target=updateCounter).start()` – jfs Mar 20 '14 at 19:02
5

Here's an answer that does not involve threads, because threads can be tricky to get right. (If you use threads you need to read up on synchronization between threads, or you can risk running into subtle bugs.)

You probably have some sort of "main loop". Maybe it looks something like this, currently:

while game.running:
    game.process()

There's nothing magical about the main loop -- you can do things besides processing input and painting to the screen here. If you want something to run once every minute you can simply do something like this:

t0 = time.time()
while game.running:
    t1 = time.time()
    if (t1-t0) >= 60.0:
        game.wood += 1
        t0 = t1 
    game.process()

If you're using certain libraries you may have your main loop hidden away inside the library. In this case you're probably starting your game more or less like this:

game.main() # this function doesn't return until your game exits

If this is the case, there will probably be a function in your library to do something equivalent to the above -- setting code to execute either every so often or at specified intervals. Look for either "idle functions" or "timers".

svk
  • 5,854
  • 17
  • 22
1

To do this you require separate threads which will be responsible for incrementing the counters. But please remember that introducing threads to any program makes it more complicated. Please refer to threading docs for details.

Also you aren't certain that particular thread will get processor's time each second, you can assume that but you aren't certain.

Marcin Pietraszek
  • 3,134
  • 1
  • 19
  • 31
1

it will run every 60 seconds.

        try {
        while (true) {
            System.out.println(new Date());
            Thread.sleep(60 * 1000);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
Mitul Maheshwari
  • 2,647
  • 4
  • 24
  • 38