millis() and timer

edited April 2016 in Questions about Code

Hi all, I found a good code to make a countdown timer. It works fine when I use the timer at the beginning of the program. But my problem is that I need the timer to work a few times in different places inside the program.

I'm doing a game, I'm using the timer as "loading" waiting. At the start of the game it works perfectly but between the first and the second level of the game I cannot use it. I guess the problem is that the timer use millis() func that shows the ms since the beginning of the program. I have no idea about how to fix this.

I only need a countdown timer (I did a function) that restart from a specific value (then go till 0) whenever I call it.

here's the code for the timer.

int timer(int timerLength) {
  int remainingTime = timerLength-millis();

  if(remainingTime/1000>0){
    int actualTime = (remainingTime/1000);
    return actualTime;
   }
  else {
    time = false;
    return 0;     
  }
}

when I need it, I call the function timer() and pass it a value in ms (let's say 10000) and it will return the seconds. the boolean variable "time", I use it in the game to decide if I can start the level or not. for example

if(time) {  // start countdown
     println(timer(10000)); // 10 seconds
     background(bgMain1); // show img
  } 
  else {  // start level

thanks

P.

Answers

  • edited November 2013 Answer ✓

    As you've noticed already, millis() returns how many milliseconds elapsed since program started:
    http://processing.org/reference/millis_.html

    To make a custom timer outta it, we just need to store apart current millis() in a variable when it starts.
    Then, millis() - startTimer returns how many milliseconds elapsed since timer had started rather than program! *-:)

  • edited November 2013

    thank you :)

    ok..I was thinking something like that..but..actually where should I place the startTimer var? This is the hierarchy of my code:

    draw() (if stat. to choose level)
      level (if stat. to choose part)
        part (= functions)
          end (special function)
    

    the function "end" (of every level) change a variable that allows the game to move to the next level. My idea was to put the timer function at the beginning of every level (before starting any part of it).

    I tried to put the startTimer variable in every place but cannot get it working. I tried to put it: inside the timer function, at the beginning of every level like this:

     if(time) { // this start timer
        fill(255,255,255,100);
        textSize(40);
        text(timer(6000),150,150); // timer
      }
      else { //countdown ends, start parts
    

    I tried to put it in the draw, before every level but still nothing..actually I guess it is because processing call everything 60 fps and then keep refreshing the value of startTimer with millis().

    I'm a bit confused at this point :/

    Thanks

    P.

  • Answer ✓

    Variables can be classified as field or local:

    1. Field-> its scope extends to whole class and remembers its value.
    2. Local-> its scope is limited to the curly bracket's block it was declared in and forgets its stored value once gone.

    Of course there are other categories too, like primitive/object & static/non-static.
    But we'll leave those for another occasion! :D

    So, if we want startTimer to survive w/ its stored value & be accessed everywhere, it gotta be declared as a field instead!
    Just place its declaration at the top of the sketch, before setup() block preferably!

  • edited December 2013

    hi, thanks..I know about the global/local variables..but my point is..ok, I've already declared startTimer at the beginning, before setup, as global..but then, where am I supposed to update it?

    thnak you

    P.

  • edited January 2014 Answer ✓

    A basic idea is to have a constant to define how many milliseconds to w8.
    Then check whether the diff. of current millis() - startTime > WAIT_CONSTANT;
    If so, update startTimer w/ current millis() again! :D

    // forum.processing.org/two/discussion/1725/millis-and-timer
    
    final int WAIT_TIME = (int) (3.5 * 1000); // 3.5 seconds
    int startTime;
    
    void draw() {
      if (hasFinished()) {
        println(WAIT_TIME/1e3 + " seconds have transpired!");
        startTime = millis();
      }
    }
    
    boolean hasFinished() {
      return millis() - startTime > WAIT_TIME;
    }
    
  • edited December 2013

    ok..it's becoming quite difficult for me :D But how do I know what should be the correct value for WAIT_TIME? If I do this I see that the timer will restart every 3.5 second..but this is not what I need..or (more probably) I missed something.

    Ok, from the beginning, I need a countdown timer. a function. I pass a value to the function (10,5...) and that's the number of seconds where the countdown will begin. I need to call this function in different places inside the game (and I can't know at what time I'll have to call the function because every level of the game may take more or less time to finish).

    thanks for your patience :)

  • edited October 2016 Answer ✓

    For such flexible schedules, creating a custom AlarmTimer is needed.

    Nonetheless, Java comes w/ its own Timer class. And I've found a usage example of it below:
    http://javarevisited.blogspot.com/2013/02/what-is-timer-and-timertask-in-java-example-tutorial.html

    And Java's reference too:
    http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html

    And here's what I've come up with:

    /** 
     * TimerTask (v1.3)
     * by GoToLoop (2013/Dec)
     * 
     * forum.Processing.org/two/discussion/1725/millis-and-timer#Item_7
     */
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    final Timer t = new Timer();
    boolean hasFinished = true;
    
    void draw() {
      if (hasFinished) {
        final float waitTime = random(10);
        createScheduleTimer(waitTime);
    
        println("\n\nTimer scheduled for "
          + nf(waitTime, 0, 2) + " secs.\n");
      }
    
      if ((frameCount & 0xF) == 0)   print('.');
    }
    
    void createScheduleTimer(final float sec) {
      hasFinished = false;
    
      t.schedule(new TimerTask() {
        public void run() {
          print(" " + nf(sec, 0, 2));
          hasFinished = true;
        }
      }
      , (long) (sec*1e3));
    }
    
  • _vk_vk
    edited December 2013 Answer ✓

    That's cool. : ) Thanks for sharing.

  • edited December 2013

    First of all, thank you for your huge help. I think I understood (more or less) your code. A question: in the if statement..what does

    & 0xF

    mean? I would like to print out the countdown seconds (5,4,3,2,1), but now is too fast.

    thanks

    P.

  • edited January 2014 Answer ✓

    B/c by default draw() is invoked @ 60 FPS, I've had to skip some print('.');. @-)
    So, I decided to only print('.'); once in 16 draw() calls!

    System variable frameCount keeps how many times draw() was called back.
    Then, frameCount & 0xF (0xF means 15) masks out all bits past least significant 4.
    It's a bitwise operation and demands binary knowledge to figure out how it works though! :(

    A non-bitwise format is: frameCount % 16 == 0. :-\"
    Now, if you prefer 1 second countdown instead, that'd be frameCount % 60 == 0. (*)

  • well..I knew &&..actually never used & :D

    last thing..I only need it to execute once. I'm trying to modify the value of hasFinished but I'm doing a mess..how can I make it execute only one time?

    thanks

    P.

  • edited December 2013 Answer ✓

    Actually, it only executes once already! 8-X

    What happens is that as soon theifblock within draw() realizes that hasFinished becametrue,
    it re-invokes createScheduleTimer(), which in turn, re-schedule() the Timer w/ another TimerTask! :-B

    It's just a simple demo on how Timer class works! You gotta implement that knowledge for your own custom needs!
    Take notice that you can place anything you wanna happen after the wait time had passed into the run() block.

  • Yes exactly, I wanted to remove the hasFinished variable as I don't wan the timer to start again and again..now I set it to false and it's ok but I wanted to clear it up as I wont need it :)

    anyway thank you it's what I needed! (at the beginning I thought it was easier :D)

    P.

  • Answer ✓

    You can get rid of that boolean completely! You just need to specify what you wanna happen once the time delay has passed!

  • well..I am so bad I can't delete it without having a non workling code :-\" .. btw this is what I ended up with, and it's exactly what I needed..thank you very much GoToLoop! :)

    import java.util.Timer;
    import java.util.TimerTask;
    
    final Timer t = new Timer();
    boolean hasFinished = true;
    
    int counter = 5;
    
    void draw() {
      countDown();
    }
    
    void countDown() {
      if (hasFinished) {
        counter = 5;
        final float waitTime = 6;
        createScheduleTimer(waitTime);
    
        println("\n\nTimer scheduled for "
          + nf(waitTime, 0, 2) + " secs.\n");
      }
    
      if (frameCount%60 == 0)
        if (counter>0) print(counter--);
        else return;
    }
    
    void createScheduleTimer(float sec) {
       hasFinished = false;
    
      t.schedule(new TimerTask() {
        public void run() {
        }
      }
      , (long) (sec*1e3));
    } 
    
  • Here is the link of good example of usage of Java Timer:-> Timer

Sign In or Register to comment.