Разрыв и дрожание в простой обработке анимации
Я новичок в обработке. Я написал следующий код с прыгающими шариками, но анимация не плавная. Я запустил приложение на разных компьютерах и иногда вижу дрожание или разрыв некоторых шариков. Я не верю, что это связано со временем расчета, так как для каждого кадра не требуется много вычислений. Более того, я прочитал обработку уже с двойной буферизацией.
Ниже приведен соответствующий код:
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);
}
}
Как я могу избавиться от дрожания и разрывов? Как убедиться, что драйвер видеокарты используется оптимально. Обратите внимание, что я использую Linux Mint 17.3 с менеджером рабочего стола MATE. Одинаковая ОС на всех протестированных ПК и одинаковое поведение.
[РЕДАКТИРОВАНИЕ 05/01/2016] После создания кругов вне экрана и даже с использованием автономного изображения размером с экран, я все еще получаю некоторые слезы. Это обновленный код:
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);
}
}
2 ответа
Оказывается, проблема заключается в рисовании множества кругов непосредственно на графике. Предварительная визуализация кругов на отдельной PGraphics для каждого круга решает проблему. Ниже приведен пересмотренный код:
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() {
frameRate(60);
size(800, 600, FX2D);
stroke(255);
background(0, 0, 0);
smooth();
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();
text((int)frameRate+"fps",10,15);
}
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);
}
image(circle, x - this.size/2 - MARGIN, y - this.size/2 - MARGIN);
}
}
Я не вижу проблем с обновлением кода и рендерингом кругов.
Используя Processing 2, я уже вижу разницу в производительности с разными рендерами.
Я добавил это в конце draw()
чтобы получить приблизительное представление о частоте кадров:
text((int)frameRate+"fps",10,15);
и это настройка я пробовал
size(800, 600,JAVA2D);
frameRate(60);
а также
size(800, 600,P2D);
frameRate(60);
и заметил с JAVA2D
frameRate придерживается довольно близко к 60fps в то время как с P2D
он падает до ~40-45 кадров в секунду
Это на OSX, но не на Linux Mint. Попробуйте FX2D
рендер в обработке 3 и посмотрите, как он сравнивается с двумя другими рендерами.
Кроме того, если на компьютере Linux Mint установлен графический процессор, драйверы установлены правильно и у вас есть время, вы можете попробовать перенести код на GLSL и отобразить его в разделе " Обработка с использованием PShader".