Processing's lag depending on screen size ?

Hello everybody,

Trying desperately to find an answer on the web, I finally ask you now :

Trying to create a responsive app with processing 3 for an android device I figured out that depending on the screen resolution the framerate slowdown and sketch become more laggy even if the smartphone is far more powerful.

For me at this time it seems not to come from the code but from the way processing compile it...

Here is my problem illustrated with a very simple sketch, the frameRate is printed in the corner :

Here on my computer :

image

And here you can see that on a S7 with high pixelDensity it's more laggy than on a S3 :( !

IMG_1778

On the other hand, I figured out that for the same screen resolution, the more the ellipse is big, the more the sketch is laggy. Could it comes from the processing libraries or what ? Is it possible to solve this problem ?

Here is another try with another more complex code (https://processing.org/examples/flocking.html) :

image

Thanks for your help

here is the first basic code if you want to try

void setup() {
  size(displayWidth, displayHeight);
  frameRate(2000);
  noStroke();
  surface.setResizable(true);
}


void draw() {
 fill(255);
 rect(0,0,displayWidth,displayHeight);

 for(int i=0;i<100;i++){
   fill(255,50,50,5);
   ellipse(width/2,height/2,i*width/150,i*width/150);
  }

  fill(0);
  textSize(width/10); 
  text(frameRate,width/15, width/10);

}

Answers

  • Well that is actually what i would expect. Higher resolution means bigger circles, so more pixels to manipulate and so it's slower. There is no way around this.

    To improve the performance of your sample-sketch, you could just draw those circles to a PGraphics once in setup() and then display them with a single call to image() in draw.

  • edited December 2016

    Well that is actually what i would expect. Higher resolution means bigger circles, so more pixels to manipulate and so it's slower. There is no way around this.

    To improve the performance of your sample-sketch, you could just draw those circles to a PGraphics once in setup() and then display them with a single call to image() in draw.

    Hey Benja,

    Thanks for this quick and good response !

    image

    I tried PGraphics and it works well for the ellipse sketch, calculating the image before running the sketch and then displaying it !!

    What if now all the loops in the sketch are needed to be calculated in real time ? Like in the flocking sketch (https://processing.org/examples/flocking.html ) where because of the animation nothing can be calculated in advance within the setup() ?

    image

    Do you see a way to have an equal framerate on every devices with processing ?

    And is this problem specific to Processing and the way it compile and display information or will it be the same with another java compiler ?

    Thanks a lot,

    Pierre

  • You can try to optimize as much as possible, but of course your device will always be limited in performance. So to have an equal framerate over all devices you will have to choose a lower framerate for all of them.

    But I don't see why you would want to do that. If you want to achieve a similiar bahaviour for animations for example, then you could use time-based animations instead of frame-based ones.

    Anyways, it's always interesting to see a comparison between different devices. If you have more than an example code feel free to share it in the forums, there a some very talented people around who can help to find potential for optimization

  • edited December 2016

    @pierrecesar --

    Do you see a way to have an equal framerate on every devices with processing ?

    You can't have a precisely equal frameRate -- because frameRate (and Java) doesn't work that way. However, there are ways of creating timing alignments that are good to within one frame (or within 1 millisecond, if you are willing to sacrifice some responsiveness and push the processor). (see for example this discussion)

    Can you say more about what you are trying to accomplish? Do you want multiple different devices to be synchronized with one another? Most solutions will be below-least-common-denominator to be reliable, e.g. if you want all three of those phones in your gif to be running identical frames they will need be running at ~36fps, slower than the slowest likely frame speed of your slowest phone. Anything faster and alignment will slip.

    frameRate(36);
    

    In general, frame-independent timing (e.g. using millis() checks to control draw event behavior) is a more robust approach to most timing problems. Then you can just focus on optimizing your pixel pushing and let the frameRate be as high as possible based on the hardware and current processor workload of whatever device it happens to be running on.

  • edited December 2016

    Hello Benja, hello Jeremydouglass,

    :x Thanks for the all the responses :) !

    After reading you, my feeling is that there is no others solutions but optimizing the code...

    Let me show you what i'm working on and perhaps you will have an idea *-:) . (I don't know if the topic is in the good section now ^^)

    I'm not trying to synchronise phones, I just experience a slowdown of the frameRate of my code with high resolutions devices which doesn't appears with lowers. I don't really want to equalize the frame rates on all the phones (sorry if misunderstanding) but just to have a decent frameRate even on a retina display. And because I tried to wrote in a responsive way I'm a little bit confused and I was not expecting that...

    I'm trying to create a very simple game to practise Java and processing. The code is quite simple, I putted the hard core at the end of the message (which is the hardest to calculate for the device, the other stuff is just PImages and some animations to make it funnier).

    The fact is that even with this simple code which is time-based, I have a very low framerate on S7 and not on S3 !

    IMG_1764 copie

    int plateformeNb=10;
    int plateformeHeight=0;
    int directionX=0;
    int directionY=0;
    int plateformeLargeur=0;
    int ballLargeur=0;
    float lastTime=0;
    int score=0;
    int scoreMax=-30;
    int e=0;
    
    
    
    float g=0;
    float bounce=0;
    float timeElapsed=0;
    float angle=0;
    float BallSpeedX=0;
    float BallSpeedY=0;
    float BallPositionX=0;
    float BallPositionY=0;
    
    
    float[] plateformeX = new float[plateformeNb+1];
    float[] plateformeY = new float[plateformeNb+1];
    
    void setup() {
    
      size(400,600);
      smooth();
      noStroke();
      plateformeHeight=width/7;
      frameRate(10000);
    
      for (int i=0; i<plateformeNb;i+=1) {
          noiseSeed(24);
          plateformeX[i]=map( noise((i+2)), 0, 1, 0, width);
          noiseSeed(10);
          plateformeY[i]=height-plateformeHeight*i;
      }
    
      BallPositionY=height/2;
      BallPositionX=width/2;
      plateformeLargeur=width/10;
      ballLargeur=width/10;
      g = width*100;
      bounce = width*14;
      mouseX=width/2;
    }
    
    void draw() {
    
    
      timeElapsed=(millis()-lastTime)/6000; //time based
      gravity();
      bouncing();
      platformGeneration();
      display();
      lastTime=millis(); //time based
    
    
    }
    
    void gravity(){
    
       BallSpeedY += timeElapsed*g;
       BallPositionY += timeElapsed*BallSpeedY; //vertical gravity 
    
       angle=map(mouseX,0,width,0.7,-0.7);
       BallSpeedX = -3000*angle;
       BallPositionX += timeElapsed*BallSpeedX;  //horizontal move
    
      if (BallSpeedY>0) { directionY=-1;}  else {    directionY=1; } //direction to know if the ball hit the platform from above or under
    
      }
    
    
    void bouncing(){
    
      for(int i=0; i<plateformeNb; i++){ // if the ball touch a platform
            if (BallPositionY>plateformeY[i] && BallPositionY<plateformeY[i]+80 && directionY<0  && BallPositionX<plateformeX[i]+1.5*plateformeLargeur/2 && BallPositionX>plateformeX[i]-1.5*plateformeLargeur/2){
               BallSpeedY = -bounce; 
               directionY=1;
            }
        }
    }
    
    void platformGeneration(){
    
    score=int((-BallPositionY)/plateformeHeight);
    
    if (score>scoreMax) {
          plateformeY[e]=-(score+plateformeNb/2)*plateformeHeight;
          plateformeX[e]=random(plateformeLargeur/2,width-plateformeLargeur/2);
    
    
    if(e==plateformeNb){e=0;}
          e+=1;
          scoreMax=score;
          }
    }
    
    
    
    void display(){
    
      fill(255);
      rect(0, 0, width, height); //background
    
      fill(0);
      for (int i=0; i<plateformeNb;i+=1) { //platforms
               rect(plateformeX[i]-plateformeLargeur/2, plateformeY[i]-BallPositionY+height/2, plateformeLargeur, plateformeLargeur/2);
             }
    
      fill(255,50,50);
      ellipse(BallPositionX,height/2,ballLargeur,ballLargeur); //ball
      textSize(width/10);
      text(frameRate,width/10,width/10);
    
    }
    
  • edited December 2016

    @pierrecesar -- got it. In that case, don't worry about sync / timing -- as @benja said, optimize.

    Keep in mind that screen resolution a squared value -- so twice the width/height = 4 times the pixels to process.

    Regarding your question:

    What if now all the loops in the sketch are needed to be calculated in real time

    Also keep in mind that draw() updates the screen only at the end of each draw loop.

    Finally, I don't recommend optimizing your code early on a learning project. Just don't worry about frame rates unless they make your game unplayable -- worry about implementing your game. Focus on optimization when it makes sense. Just to pick one example, you could draw a series of platforms once onto a long PGraphics tile, then scroll the tile past -- this approach can be much faster than redrawing the platforms in a slightly different position each time. However, first you should probably just focus on figuring out platforms -- speed up how they are created later.

  • edited December 2016

    Thanks @jeremydouglass for this clear answer and merry Xmas !

    I was not aware of all these constraints and it answers clearly my first question ! Reading about java optimisation I figured out that - as you said - my code is not really optimized right now and I'll try to take this in consideration in the future ^^

    Just don't worry about frame rates unless they make your game unplayable

    The fact is that - as you can see on the picture - my game is not playable right now on my S7 because of the framerate (17FPS) witch is a big deception :( ...

    Tell me if i'm wrong but could I downgrade the resolution to make the game run faster ? Make processing calculate the game half the resolution but display it fullscreen (like in most of PC games options' menu where you can chose to set the resolution to 1280*720 even if your screen is full HD to win framerates...)

    PS: And even though the graphism quality will be affected by such an operation, my Pimages are far from the resolution they are displayed on an S7 (they are 200*200px) so it's really a waste of framerates on my side ;;)

    Is that operation possible for processing ?

    Thanks a lot ~O)

  • Hello the processing forum,

    A good news, I tried FX2D and its pretty amazing. It speeds up so much compared to P2D and OPENGL. I got an incredible framerate on my app up to 600fps against 150 before (on the desktop not S7). But it seems that FX2D is not available for processing android right now, I am right ?

    Thanks.

  • This difference happens only when you are using a custom frameRate. If you don't need, delete this line and all should get back to normal.

    I know this topic is old, but maybe this could help someone looking for a answer.

Sign In or Register to comment.