Inconsistent Framerate - please help

edited February 2015 in How To...

My goal is to achieve 60fps consistently. If I set frameRate(100); it never drops below 60 - so the program is capable of runnung fast enough. The problem is though on either setting - frameRate(60 and frameRate(100) - there are noticeable "jumps" of the frame rate. It will be at 55 at one point and then at 65 a fraction of a second later. This leads to a stuttery and not so smooth outcome. I use the default renderer and I only need to render a couple of dozen shapes and text for the framrate.

Are there any tricks and tips to achieve a more consistent framerate? Any idea why this inconsistency occurs?

P.s.: I also noticed something very strange. If I let another java program run in the background (it's actually a trident project, but I don't think it's relevant) the framerate could not be more stable. Even on frameRate(100) it never even drops 1 fps above or below 100. I assume it may have to do with a second CPU core beeing used or sth like that. But I suspect there could be more going on, it's uncanny how it jumps a good 3-10 fps at one point and as soon as I open the second java program it's crazy stable. When I close the program it's starting to stutter again like before.

Tagged:

Answers

  • If you really care about having extremely smooth animations, then don't depend on a particular framerate.

    Instead, measure the amount of time that has passed between frames, and do your animation accordingly. For example, if your framerate is running low, then make your animation "faster", so it looks like your animation is keeping up. Similarly, if your framerate is running high, then slow your animation down.

    There are plenty of tutorials on this. Googling "framerate independent movement" is a good start.

  • I'm not sure, but I think you may have misunderstood my problem (or rather I may have explained not enough).

    I actually do use time as the basis for my animation. I have circles rotating around the center of the display. Everytime draw() is called I look at millis() and calculate the coordinates of all circles accordingly (I would post a sketch but I use processing in eclipse and the object structure is not trivial). It's stuttery because if you have 55fps at one point and then 65fps soon after a different amount of time moved on between draws.

    Did I understand your comment correctly that you thought I did not do this yet, or do you mean I have to do more complex calculations? I'm a little bit confused.

  • Can you post an MCVE of your sketch?

  • Okay nevermind - after rereading your post, I think I got what you meant. I have to calculate the amount of time past since the last draw() was called and draw my shapes accorcingly.

    Thanks for the tip - I will try to implement this. One question that comes to my mind though - with this method - can you guarantee a certain consistent speed of the shapes?

  • You might look at this guide to animation

  • @quark: I looked up your example and with an inconsistent framerate this example will stutter as well (in my tests).

    @KevinWorkman: I will work out a MCVE and post it soon.

    I think my first impulse was right - I need to get to a more consistent framerate if I ever want to have a smooth sketch.

  • I wrote this up before I saw quark's example, so there is some overlap, but this seems to work okay for me:

    float ballY = 250;
    float deltaPerSecond = 100;
    long lastFrame = millis();
    
    void setup() {
      size(500, 500);
      frameRate(30);
    }
    
    void draw() {
    
      frameRate(40+random(20));
      println(frameRate);
    
      long thisFrame = millis();
      background(0); 
    
      float secondsElapsed = (thisFrame-lastFrame)/1000.0;
    
      ballY = ballY + deltaPerSecond*secondsElapsed;
    
      if (ballY < 0 || ballY > height) {
        deltaPerSecond *= -1;
      }
    
      ellipse(width/2, ballY, 10, 10);
    
      lastFrame = thisFrame;
    }
    

    Notice that I'm constantly changing the FPS to simulate your environment, but since I'm basing the ball's speed off of the elapsed time between frames, the ball will always move at the same speed.

  • You are never going to get a guarenteed steady framerate because your computer is multitasking so other processes are happening at the same time. ALL you can do is base the animation on elapsed time as shown in my example, and in the code provided by @KevinWorkman. That is the ONLY way you can guarenteee that a sprite moves at constant speed.

    If you program it correctly you shouldn't notice anything at 60fps even if it drops or increases by 10fps. For very fast sprites this may become an issue with collision detection but then there are different techniques you can use for that as well.

  • edited February 2015

    @KevinWorkman: Yes it will move at the same speed - but will it be smooth?

    In your example it seems to be working but I think it's more an optical illusion caused by the small ball and one-directional movement. Also the framerate actually does not fluctuate that much (at first I thought that framerate(40 + rand(20)); would change it +0 to +20 but that is not the case). I was just finishing the MCVE but I think yours is probably better. I changed some stuff - can you see the jittering? Run this sketch and then comment out the framrate manipulation. See the difference? That's why I want consistent framerates.

    (How do I post code to this forum?)

    ```java

    float ballY = 250;

    float ballX = 250;

    float deltaPerSecondY = 500;

    float deltaPerSecondX = 490;

    long lastFrame = millis();

    void setup() {

    size(displayHeight -100, displayHeight - 100);

    }

    void draw() {

    int rand = int((random(2)-1) * random(50));

    println("rand: " + rand);

    frameRate(60+rand);

    println("fr: " + frameRate);

    long thisFrame = millis();

    background(0);

    float secondsElapsed = (thisFrame-lastFrame)/1000.0;

    ballY = ballY + deltaPerSecondY * secondsElapsed;

    ballX = ballX + deltaPerSecondX * secondsElapsed;

    if (ballY < 0 || ballY >= height-30) {

    deltaPerSecondY *= -1;
    

    }

    if (ballX < 0 || ballX >= width-30) {

    deltaPerSecondX *= -1;
    

    }

    ellipse(ballX, ballY, 50, 50);

    lastFrame = thisFrame; }

    ```

  • @quark: Thanks for the reply. I already had constant speed. I just want to achieve the most consistent framerate possible. I think it's weird because if I set frameRate(100) it never drops below 90, but if I set frameRate(60) it's dropping below 60. Also it's going as much up as 70. But of course - if there is no way to improve this then I have to deal with it -.-

  • Okay for anybody in a similar situation I found a fix. Switching to render mode P2D solved it for me. Now it runs completely stable and smooth. The shapes do not look as "sharp" anymore, but I need the constant framerate and non jittery movement.

  • @michajg: I am also facing the same problem. Can you kindly share the solution code :)

  • edited September 2016

    @Abdul, when @michajg said

    Switching to render mode P2D solved it for me

    that refers to the P2D renderer. In code, you use it adding "P2D" as an argument to size() in setup, e.g.

    void setup() {
      size(500, 500, P2D);
      frameRate(40);
    }
    
Sign In or Register to comment.