2016-04-29 7 views
0

Ich bin neu in der Verarbeitung. Ich habe den folgenden Code mit springenden Bällen geschrieben, aber die Animation ist nicht glatt. Ich habe die Anwendung auf verschiedenen Computern ausgeführt und kann gelegentlich ein Zittern oder Reißen von Bällen sehen. Ich glaube nicht, dass es sich um die Berechnungszeit handelt, da für jeden Frame nicht viel berechnet wird. Außerdem habe ich gelesen, dass die Verarbeitung bereits doppelt gepuffert ist.Tearing und Jitter in einer einfachen Verarbeitung Animation

Im Folgenden ist der betreffende 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); 

    } 

} 

Wie kann ich für den Jitter loszuwerden und reißen? Wie stelle ich sicher, dass der Grafikkartentreiber optimal genutzt wird? Beachten Sie, dass ich Linux Mint 17.3 mit MATE Desktop Manager verwende. Gleiches O.S. auf allen getesteten PCs und gleiches Verhalten.

[EDIT 05/01/2016] Nach dem Erstellen der Kreise Off-Screen und sogar mit einem Offline-Bild die Größe des Bildschirms, bekomme ich immer noch einige Tearing. Dies ist der aktualisierte 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); 
    } 

} 
+0

Dieser Code läuft gut für mich auf Windows 10. Können Sie einen Screenshot von genau, was Sie reden? Ändern Sie Ihren Code möglicherweise, um hartcodierte Werte zu verwenden, die das Verhalten verursachen, anstatt die Funktion 'random()' zu verwenden. –

+0

@KevinWorkman Das Verhalten ist unabhängig von der Größe der Bälle konsistent. Ich bekomme das Reißen jedes Mal, wenn ich die App laufen lasse. Ich habe es jedoch nicht unter Windows getestet. Ich konnte es nicht screenen. Videoaufnahmen mit 60 fps mit VLC konnten nicht erfasst werden. Es ist ein horizontales Reißen, wobei der untere Teil des Balls verschoben wird. – Tarik

+0

Das wird ziemlich schwierig zu debuggen, wenn wir das Verhalten nicht wiederholen können. Welcher Ball? Berührt sich die zufällige Bewegung überhaupt, oder kannst du einfach die Bewegungsrichtung fest codieren? Kannst du mit nur einem Ball ein kleineres Beispiel erstellen?Es gibt eine Menge extra Code hier. Ist alles auf dein Problem bezogen? Wenn nicht, können Sie das Beispiel überhaupt vereinfachen? –

Antwort

0

Ich sehe kein Problem mit dem Code aktualisieren und Rendern Kreise.

Verwendung von Verarbeitung 2 Ich kann bereits einen Unterschied in der Leistung mit verschiedenen Renderern sehen.

Ich habe dies von draw() am Ende hinzufügen, um eine grobe Vorstellung von Bildrate:

text((int)frameRate+"fps",10,15); 

und es Setup Ich habe versucht,

size(800, 600,JAVA2D); 
frameRate(60); 

und

size(800, 600,P2D); 
frameRate(60); 

und bemerkt mit JAVA2D der frameRate Sticks ziemlich nah an 60fps während mit P2D fällt auf ~ 40-45fps

Dies ist auf OSX, aber nicht auf Linux Mint. Probieren Sie den Renderer FX2D in Processing 3 aus und sehen Sie, wie er mit den anderen beiden Renderern verglichen wird.

Zusätzlich, wenn es eine GPU auf dem Linux Mint Computer gibt, Treiber sind ordnungsgemäß installiert und Sie haben die Zeit, Sie könnten versuchen, den Code zu GLSL zu portieren und es in Verarbeitung mit PShader rendern.

+0

Ich habe versucht, es auf Windows zu laufen und was auffällt ist, dass etwa alle 2-3 Sekunden die Kugeln für einen Bruchteil einer Sekunde einfrieren. Ich überprüfte die CPU-Auslastung und es ist nahe Null. Ich habe verschiedene Renderer unter Linux vergeblich ausprobiert. – Tarik

+0

OK, ich habe gerade das FX2D-Flag unter Windows hinzugefügt und es friert jetzt weniger oft, wieder für einen winzigen Sekundenbruchteil. – Tarik

+0

Die Bildrate Zeile unter Linux hinzugefügt und ich bekomme 59fps-60fps. Wenn ich die Bildrate auf 100 fps setze, erhalte ich 99 fps-100 fps. Als solches scheint es nicht mit der Rechenleistung zu tun zu haben, die Berechnungen sind ziemlich einfach. – Tarik

1

Es stellt sich heraus, dass das Zeichnen von vielen Kreisen direkt auf der Grafik das Problem verursacht. Das Vorrendern der Kreise auf separaten PGraphics für jeden Kreis löst das Problem. Das Folgende ist der überarbeitete 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() { 
    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); 
    } 

} 
Verwandte Themen