Search code examples
javatimermillisecondsprocessing

Processing P5 - Timer issue with millis()


I am making a little game in Processing which is similar to those Guitar Hero style games and I am trying to do 2 things:

  1. When the game loads, stop the time from moving
  2. During the game, allow for Pause functionality

Now, I know I cant stop the time since the millis() returns the milliseconds since the application launched, so my timer will need to be millis() - millis() at the start to equal zero, so when the user presses START, they can obviously start at the start. The game reads a file at the start, similar to a subtitles file, that has the note to be played and the time in milliseconds that it should appear on screen.

My problem is, when I pause the game, the timer keeps going and when I unpause the game, all the notes get "bunched up" due to my logic, as you'll see from my code.

Can someone suggest a better algorithm than the one I'm using? Its late and I've been working on this all day and night. I think the problem is with the for() below:

public void draw()
{
    if (gameInProgress)
    {
        currentTimerValue = millis(); // Update the timer with the current milliseconds
        // Check to see if the note times falls between the current time, or since the last loop (difficult to match exact millisecond)
        for(int i=0 ; i<songNotes.length ; i++)
        {
             if( songNotes[i].getStartTime() > previousTimerValue && songNotes[i].getStartTime() <=currentTimerValue)
                notes.add(songNotes[i]);
        }

        noStroke();
        textFont(f,18);
        drawButtons();  //Draws coloured buttons relating to Button presses on the controller
        drawHighScoreBox(); // Draws high score box up top right
        drawLines();  // Draws the strings
        moveNotes();  // Moves the notes across from right to left
        //Now set the cutoff for oldest note to display
        previousTimerValue=currentTimerValue;  //Used everytime on the following loop
    }
    else
    {
        drawMenu(); // Draw the Main/Pause menu
    }
}

NOTE: The boolean gameInProgress is set below when the users presses the pause button, eg "P", and songNotes is an array of objects of type Note that I wrote myself. It has 2 member variables, noteToBePlayed and timeToBePlayed. The method getStartTime()returns timeToBePlayed which is a millisecond value.

Any help is appreciated. Thanks


Solution

  • How about having another integer to store time when you pause and use that to offset the game timer ?

    So, in 'gameInProgress' mode you update currentTimerValue and previousTimerValue and in 'paused/menu' mode you update a pausedTimerValue, which you use to offset the 'currentTimerValue'. I hope this makes sense, it sounds more complicated in words, here's what I mean:

    boolean gameInProgress = true;
    int currentTimerValue,previousTimerValue,pausedTimerValue;
    void setup(){
    
    }
    void draw(){
      if(gameInProgress){
        currentTimerValue = millis()-pausedTimerValue;
        println("currentTimerValue: " + currentTimerValue + " previousTimerValue: " + previousTimerValue);  
        previousTimerValue=currentTimerValue;
      }else{
        pausedTimerValue = millis()-currentTimerValue;
      }
    }
    void mousePressed(){
      gameInProgress = !gameInProgress;
      println("paused: " + (gameInProgress ? "NO" : "YES"));
    }
    

    Click the sketch to toggle modes and look in the console for times. You'll notice that you only loose a few millis between toggles, which is acceptable.