frameRate, frameCount and millis

By default Processing will execute the draw() function 60 times a second. Each time it is executed it creates a new frame which is then displayed. So the display is updated 60 fps (frames per second). I should point out that this is not the case for JavaScript since each frame is drawn on demand, although it is possible to trigger those demands 60 times a second.

The frameRate(float fps) method can be used to set the desired frame rate and the variable frameRate holds the instantaneous frame rate (as calculated by Processing). There is another useful variable called frameCount, which is the number of frames rendered since the sketch started. Finally we have millis() which returns the number of milliseconds since the sketch started running.

Both the movies below show the output of sketches where the desired frame rate has been set with the statement frameRate(60).

In this sketch the graph plots the value of frameRate for every frame. We can see that the frame rate starts off low and quickly rises towards the desired value but then there is significant variation between frames. Once it has settled down the sketch uses the frame rate reported by Processing to calculate the average frame rate, which is plotted as a red line. Notice that this average does not match the desired frame rate of 60fps.

So although we could use frameRate to perform time dependent processing the difference from reality would be undesirable.

It is possible to calculate the true average frame rate and this is shown by the green line.

For a real time application we need to measure the elapsed time between frames. Processing provides a handy method called millis() which returns the time since the sketch started in milliseconds, using this it is simple to calculate the elapsed time between frames.

In this sketch the frame rate has been set to 60fps and the graph shows the elapsed time between frames. At 60fps the elapsed time should be 16.667ms but the millis method returns an integer so it is generally 16 or 17ms but there are some values either side of this range.

So what if we want a circle to traverse the screen at exactly 60 pixels per second? This sketch demonstrates how to do it. If you run this code in Processing you will see the green circle traverse the window at exactly 60 pixels per second. Since the sketch is 600 pixels wide it will take 10 seconds to traverse the display. You can change the frame rate in line 9 but it still travels at 60 pixels per second, although the movement will be more jerky at low frame rates.

int currTime, prevTime;  // milliseconds
float elapsedTime;       // seconds
float speed = 60;        // speed in pixels per second
float x0, x1;

void setup(){
  size(600, 200);
  frameRate(200);
  noStroke();
  // This should be last line in setup
  currTime = prevTime = millis();
}
 
void draw(){
  // Using elapsed time between frames for accuracy
  currTime = millis();
  elapsedTime = (currTime - prevTime) / 1000.0;
  prevTime = currTime;  // set it up for the next frame
  // Start frame rendering
  background(0, 0, 128);
  // update the position of the circle and draw it
  x0 += speed * elapsedTime; 
  x0 %= width;
  // wrap round screen width fill(0,255,0);
  ellipse(x0, 64, 20, 20);
} 

We could use frameRate instead by changing line 21 to

x0 += speed / frameRate;

but because the average frame rate measured using frameRate is greater than the actual frame rate the ball travels slower than 60 pixels per second. Although the difference is not great there is no reason why we should accept it.

Leave a Reply

Your email address will not be published. Required fields are marked *