Changing the frameRate

Hi guys,

I was trying to change the framerate of a p5.js sketch while the sketch is running. However I wasn't successful. Then I discovered the Instance Mode (https://p5js.org/examples/examples/Instance_Mode_Instantiation.php) to run multiple sketches. Using this I thought I could delete an old sketch (with sketch.remove()) and create a new one that runs the setup like the old one. Im trying something like this:

var rate = 40;
var sketchInit = function(sketch){
     sketch.setup = function(){
          sketch.createCanvas(300, 300);
          sketch.background(0);
          sketch.frameRate(rate);
     }

     sketch.draw = function(){
          // some stuff that gets drawn
     }
}

var mysketch = new p5(sketchInit);

// later on in the code ...

if(someEventHappens){
    rate = 80;
    mysketch.remove();
    mysketch = new p5(sketchInit);
}

Basically, what I'm trying to achieve here is create a sketch, run the sketch, and if some event happens change the rate variable and start a new sketch with the updated frameRate. However the sketch isn't updating the frameRate.

I can debug this code in my browser to the point where I can see the setup function being executed. So I expect the frameRate to change.

So the questions are:

Can I change the frameRate in a running sketch? If not, how can I change the frameRate in a new sketch?

Tagged:

Answers

  • Is your device capable of the required framerate?

  • edited May 2016

    yes, but is there a difference between the framerate in processing and the framerate in p5js? I don't know if the browser is capable of a higher framerate.

  • Answer ✓

    I don't know if the browser is capable of a higher framerate.

    If you're relying on consistent changes to framerate then you also have to consider that the same browser running on different hardware is also going to deliver different framerates. As such the only way to return consistent results would be to first test what framerate the browser running the sketch is capable of; and then slow/speed up based on the maximum. This will of course add another layer of complexity to your sketch :(|)

  • Yeah, I couldn't see any changes in the framerate because the framerate was already at the maximum. The code was fine. Thanks for the answers!

  • A better approach might be to use time based animation: where you keep track of where things should be based on time and independently of frame rate. You can then make adjustments to speed without changing frame rate and do so from within a single sketch...

  • @joliver: I found a clear explanation of time based animation and adapted it to enable changing sketch speed:

    "use strict";
    
    var sketchSpeed = 1;
    var targetFPS = 30;
    
    window['$p'] = new p5(function (p) {
    
        var ball1;
        var ball2;
    
        p.setup = function () {
            p.createCanvas(600, 400);
    
            ball1 = new Ball(0, p.height * 0.25, 1);
            // this ball moves twice as fast as the first
            ball2 = new Ball(0, p.height * 0.75, 2);
            // add sketchspeed toggle
            addToggle();
        };
    
        p.draw = function() {
            p.background('#eee');
    
            ball1.move();
            ball2.move();
        };
    
    }, "sketch01");
    
    
    // simple ball class
    function Ball(x, y, vx) {
      this.x = x;
      this.y = y;
      this.vx = vx || 1;
      this.tick = new Date().getTime();
    }
    
    Ball.prototype.move = function() {
    
        this.tock = new Date().getTime();
        this.delta = this.tock - this.tick;
    
    
        $p.fill('#f90');
        $p.ellipse(this.x, this.y, 40, 40);
    
    
        this.x += calcSpeed(this.delta, this.vx);
        if(this.x > $p.width) {
            this.x = 0;
        }
    
        this.tick = this.tock;
    };
    
    // add button
    function addToggle() {
        var btn = document.createElement('div');
        btn.setAttribute('style', "padding: 1em;" + 
                     "background: #09f;" + 
                     "width: 200;" +
                     "text-align: center;" +
                     "margin: 1em 0 0 0; " +
                     "cursor: pointer; " +
                     "color: #fff; " +
                     "font-size: 18pt;" + 
                     "border-radius: 0.25em;")
        btn.innerHTML = "toggle speed";
        btn.addEventListener('click', function() {
            sketchSpeed = sketchSpeed === 1 ? 2 : 1;
        });
    
        var sketch = document.getElementById('sketch01');
        sketch.appendChild(btn);
    
    }
    
    // adapted from: 
    // http: + //codetheory.in/time-based-animations-in-html5-games-why-and-how-to-implement-them/
    function calcSpeed(delta, speed){
        return  (speed * delta) * ((targetFPS*sketchSpeed)/100);
    };
    

    In principle this approach looks practical enough; but it's possible you'll run into problems because of floating point inaccuracies: over time things may start falling out of sync.

  • Of course, time based is indeed best, but will add big layer of complexity.

  • time based is indeed best, but will add big layer of complexity

    Maybe; maybe not; but certainly no more complexity than trying to reinstantiate your sketch with a different framerate whilst preserving variable values... :(|)

    The example I posted above seems fairly trivial in comparison; but from my tests definitely does have precision issues. It could simply be general floating point inaccuracies but I think they're compounded/exaggerated by the calcSpeed() calculation; meaning they present themselves too soon for my liking.

    I'm just experimenting with a different approach. Will hopefully be able to post another demo later ;)

  • Sadly have run out of time for today and unlikely to be able to revisit this till the weekend :(

    Managing a single delta appears to produce better results - and is probably fine for general use - but it's proving quite difficult to get really accurate results when having to contend with floating point inaccuracies :/

    I would assume this issue also applies when using just the standard draw loop though...

  • If you are trying to only change the frame rate then there is no need to call frameRate(); in the setup. Just call frameRate(); in Draw(){}. If the rest of your sketch remains the same I would suggest this to adjust the frame rate.

     var rate = 40;
    
     function setup(){
          createCanvas(300, 300);
          background(0);
     }
    
     function draw(){
          frameRate(rate);
          //sketch stuff here
          if(someEventHappens){
               rate = 80;
          }
     }
    
  • @mikessler: that's fine in principle; but the OP is looking for precise changes in sketch speed. Adjusting the framerate is far from ideal for this purpose since it's also dependent on the performance of the host browser.

  • @blindfish I use this commonly as I use p5.js to drive LEDs. I understand the OP has other concerns, but other people may also have this question for different reasons.

    One note, I had a sketch that would only run around 22 frames per second. I adjusted the sketch to 20 fps to try to get the sketch to run smoother. When I logged the frame rate it was lowered to around 15 fps instead of a steady 20 fps. So also there might be unintended consequences for adjusting the frame rate instead of the timing like you had said.

Sign In or Register to comment.