Tips for speeding up this sketch

I’m new to Processing, and have my project working but with some performance issues.

Basically I have 10 images that I’m scaling and moving (with lerp) when a key is pressed. Eventually I’d like to get this up to 100 images, but the performance is pretty bad with just 10.

Here’s the code:

Shard[] shards = new Shard[10];

void setup() {
  size(800, 600);

  for (int i = 0; i < 10; i++) {
    shards[i] = new Shard("square.png");
  }
  smooth();
  frameRate(30);
}

void keyPressed() {
  if (key == ' ') {
    for (int i = 0; i < 10; i++) {
      shards[i].triggerPulse();
    }
  }
}

void draw(){
  background(0);

  for (int i = 0; i < 10; i++) {
    shards[i].move();
    shards[i].display();
  }
}

This is the code for the Shard class:

class Shard {
  PVector target;
  PVector origin;
  PVector current;

  float targetScale;
  float startScale;
  float currentScale;

  float speed;
  PImage image;

  Shard(String imagePath) {
    origin = new PVector(width/2, height/2);
    target = new PVector(random(width), random(height));
    current = new PVector(origin.x, origin.y);
    currentScale = 1.0;
    startScale = 1.0;
    targetScale = 1.0;
    speed = 0;
    image = loadImage(imagePath);
  }

  void display() {
    imageMode(CENTER);
    image(image, current.x, current.y, image.width * currentScale, image.height * currentScale);
  }

  void triggerPulse() {
    target = new PVector(random(width), random(height));
    targetScale = random(2.0);
  }

  void move() {
    speed += 0.1;

     // Compute the new positions
    current.x = lerp(current.x, target.x, sin(speed));
    current.y = lerp(current.y, target.y, sin(speed));
    currentScale = lerp(currentScale, targetScale, sin(speed));

    if (current.x == target.x || current.y == target.y) {
      target = new PVector(origin.x, origin.y);
      targetScale = startScale;
      speed = 0;
    }

    if (current.x == origin.x || current.y == origin.y) {
      speed = 0;
    }
  }
}

Any obvious mistakes here or improvements I can make to speed this up?

1 Like

while you move and re-scale all pictures the FPS will drop,
but when stop moving actually no use to show “many” pictures, only the ONE.
example:

// https://discourse.processing.org/t/tips-for-speeding-up-this-sketch/8468
int many =10;
Shard[] shards = new Shard[many];
int showid = 0;

void setup() {
  size(800, 600);
  for (int i = 0; i <many; i++) shards[i] = new Shard("square.png", i);
}

void keyPressed() {
  if (key == ' ') {
    for (int i = 0; i <many; i++)  shards[i].triggerPulse();
    showid = (int)random(many);                               // select next random picture to show
    println("new pic "+showid);
  }
}

void draw() {
  surface.setTitle("my gallery "+nf(frameRate,1,1));
  background(200, 200, 0);
  for (int i = 0; i < many; i++) shards[i].moveAndshow();
}


class Shard {
  PVector target;
  PVector origin;
  PVector current;

  float targetScale;
  float startScale;
  float currentScale;

  float speed;
  PImage image;
  int id;

  Shard(String imagePath, int id) {
    origin = new PVector(width/2, height/2);
    target = new PVector(random(width), random(height));
    current = new PVector(origin.x, origin.y);
    currentScale = 1.0;
    startScale = 1.0;
    targetScale = 1.0;
    speed = 0;
    image = loadImage(imagePath);
    this.id = id;
  }

  void display() {
    imageMode(CENTER);
    image(image, current.x, current.y, image.width * currentScale, image.height * currentScale);
    fill(0);
    text(id, width/2, height/2);
  }

  void triggerPulse() {
    target = new PVector(random(width), random(height));
    targetScale = random(2.0);
  }

  void moveAndshow() {
    if (current.x == target.x || current.y == target.y) {
      target = new PVector(origin.x, origin.y);
      targetScale = startScale;
      speed = 0;
    } else {
      speed += 0.1;
      //                                                              Compute the new positions
      current.x = lerp(current.x, target.x, sin(speed));
      current.y = lerp(current.y, target.y, sin(speed));
      currentScale = lerp(currentScale, targetScale, sin(speed));
    }

    if (current.x == origin.x || current.y == origin.y)   speed = 0;
    // show it from here, not need extra call from draw
    if ( speed > 0 )         display();                                 // show all while moving     // very slow               
    else if ( id == showid ) display();                                 // show only one random pic
  }
}

2 Likes

i think if you switch over to the P2D renderer you will get much better results.

this runs 100 well on my machine

int amount;
Shard[] shards;

void setup() {
  size(800, 600, P2D);

  amount = 100;

  shards = new Shard[amount];
  for (int i = 0; i < amount; i++) {
    shards[i] = new Shard("square.png");
  }
  
  imageMode(CENTER);
  smooth();
  frameRate(30);
}

void keyPressed() {
  if (key == ' ') {
    for (int i = 0; i < amount; i++) {
      shards[i].triggerPulse();
    }
  }
}

void draw(){
  background(0);

  for (int i = 0; i < amount; i++) {
    shards[i].move();
    shards[i].display();
  }
}

class Shard {
  PVector target;
  PVector origin;
  PVector current;

  float targetScale;
  float startScale;
  float currentScale;

  float speed;
  PImage image;

  Shard(String imagePath) {
    origin = new PVector(width/2, height/2);
    target = new PVector(random(width), random(height));
    current = new PVector(origin.x, origin.y);
    currentScale = 1.0;
    startScale = 1.0;
    targetScale = 1.0;
    speed = 0;
    image = loadImage(imagePath);
  }

  void display() {
    image(image, current.x, current.y, image.width * currentScale, image.height * currentScale);
  }

  void triggerPulse() {
    target.x = random(width);
    target.y = random(height);
    targetScale = random(2.0);
  }

  void move() {
    speed += 0.1;

     // Compute the new positions
    float n = sin(speed);
    current.x = lerp(current.x, target.x, n);
    current.y = lerp(current.y, target.y, n);
    currentScale = lerp(currentScale, targetScale, n);

    if (current.x == target.x || current.y == target.y) {
      //if(PVector.dist(current, target) < 10) {
      target.x = origin.x;
      target.y = origin.y;
      targetScale = startScale;
      speed = 0;
    }
  }
}

if you mix this with kll’s great optimizations i think you will have found your solution.

2 Likes

Awesome - switching renderers made a huge difference.

Thank you!

Hmm - eventually, I’ll be using different images with varying levels of opacity, so they will need to remain visible even when not moving.

Creating a variable to hold the number of shards is a great idea though, thank you!