I am new to processing. I wrote the following code with bouncing balls but the animation is not smooth. I have ran the application on various computers and I can occasionally see some jitter or tearing of some balls. I do not believe that it is related to the calculation time as it there are not much calculations involved for each frame. Moreover, I have read the processing is already double buffered.
The following is the concerned code:
final int MAX_BALLS = 50;
final int DISPLAY_WIDTH = 800;
final int DISPLAY_HEIGHT = 600;
final float MIN_SPEED = 1;
final float MAX_SPEED = 5;
final float MIN_SIZE = 30;
final float MAX_SIZE = 50;
Ball[] balls = new Ball[MAX_BALLS];
void setup() {
size(800, 600);
stroke(255);
background(0, 0, 0);
for (int i=0; i<balls.length; i++) {
balls[i] = new Ball(random(MIN_SIZE, MAX_SIZE), random(0, DISPLAY_WIDTH), random(0, DISPLAY_HEIGHT), random(MIN_SPEED, MAX_SPEED), random(MIN_SPEED, MAX_SPEED), 0, DISPLAY_WIDTH, 0, DISPLAY_HEIGHT);
}
}
void draw() {
clear();
for (int i = 0; i<balls.length; i++)
balls[i].draw();
}
class Ball {
private float size;
private float x;
private float y;
private float vx;
private float vy;
private float minx;
private float maxx;
private float miny;
private float maxy;
private float r;
private float g;
private float b;
public Ball(float size,float x, float y, float vx, float vy, float minx, float maxx, float miny, float maxy) {
this.size = size;
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.minx = minx;
this.maxx = maxx;
this.miny = miny;
this.maxy = maxy;
r = (int) random(30, 255);
g = (int) random(30, 255);
b = (int) random(30, 255);
}
void draw() {
x = x + vx;
if (x + size/2 > maxx) {
vx = -vx;
x = 2 * maxx - (x + size);
} else if (x - size/2 < minx) {
vx = -vx;
x = 2 * minx - (x - size);
}
y = y + vy;
if (y + size/2 > maxy) {
vy = -vy;
y = 2 * maxy - (y + size);
} else if (y -size/2 < miny) {
vy = -vy;
y = 2 * miny - (y - size);
}
stroke(r,g,b);
fill(r,g,b);
ellipse(x, y, size, size);
}
}
How can I get rid of the jitter and tearing? How do I ensure that the graphics card driver is used optimally. Note that I use Linux Mint 17.3 with MATE desktop manager. Same O.S. on all tested PCs and same behavior.
[EDIT 05/01/2016] After generating the circles off-screen and even using an offline image the size of the screen, I still get some tearing. This is the updated code:
final int MAX_BALLS = 50;
final float MIN_SPEED = 1;
final float MAX_SPEED = 5;
final float MIN_SIZE = 30;
final float MAX_SIZE = 50;
Ball[] balls = new Ball[MAX_BALLS];
PGraphics img;
void setup() {
frameRate(60);
fullScreen();
img = createGraphics(width, height);
img.stroke(255);
img.smooth();
for (int i=0; i<balls.length; i++) {
balls[i] = new Ball(random(MIN_SIZE, MAX_SIZE), random(0, width), random(0, height), random(MIN_SPEED, MAX_SPEED), random(MIN_SPEED, MAX_SPEED), 0, width, 0, height);
}
}
void draw() {
img.beginDraw();
img.background(0,0,0);
img.clear();
clear();
for (int i = 0; i<balls.length; i++)
balls[i].draw();
img.text((int)frameRate+"fps",10,15);
img.endDraw();
image(img, 0, 0); // Put the whole image at once on the screen
}
class Ball {
private float size;
private float x;
private float y;
private float vx;
private float vy;
private float minx;
private float maxx;
private float miny;
private float maxy;
private PGraphics circle;
private final int MARGIN = 10; // Margin to avoid circle to be drawn slightly outside the square
public Ball(float size,float x, float y, float vx, float vy, float minx, float maxx, float miny, float maxy) {
this.size = size;
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.minx = minx;
this.maxx = maxx;
this.miny = miny;
this.maxy = maxy;
int r = (int) random(30, 255);
int g = (int) random(30, 255);
int b = (int) random(30, 255);
circle = createGraphics((int) this.size + 2*MARGIN, (int) this.size + 2*MARGIN);
circle.beginDraw();
circle.background(0, 0);
circle.fill(r, g, b);
circle.ellipse(MARGIN + this.size/2, MARGIN + this.size/2, this.size, this.size);
circle.endDraw();
}
void draw() {
x = x + vx;
if (x + size/2 > maxx) {
vx = -vx;
x = 2 * maxx - (x + size);
} else if (x - size/2 < minx) {
vx = -vx;
x = 2 * minx - (x - size);
}
y = y + vy;
if (y + size/2 > maxy) {
vy = -vy;
y = 2 * maxy - (y + size);
} else if (y -size/2 < miny) {
vy = -vy;
y = 2 * miny - (y - size);
}
img.image(circle, x - this.size/2 - MARGIN, y - this.size/2 - MARGIN);
}
}
I don't see any issue with the code updating and rendering circles.
Using Processing 2 I can already see a difference in performance with different renderers.
I've add this at the end of
draw()
to get a rough idea of frame rate:and it setup I've tried
and
and noticed with
JAVA2D
the frameRate sticks pretty close to 60fps while withP2D
it drops to ~40-45fpsThis is on OSX though, not on Linux Mint. Try the
FX2D
renderer in Processing 3 and see how it compares with the other two renderers.Additionally, if there is a GPU on the Linux Mint computer, drivers are properly installed and you have the time, you could try to port the code to GLSL and render it in Processing using PShader.