Flackern trotz DoubleBuffering

Status
Nicht offen für weitere Antworten.

moormaster

Top Contributor
Hi,

ich versuche mich gerade daran, einen Ausschnitt eines Feldes aus Objekten zu zeichnen.

Dazu gibt es ein GameObject, welches update und paint Methoden definiert:

Code:
 public class GameObject
 {
   int posX, posY, width, height;
  ...
  public void update(Graphics g)
  {
   if (background != null)
   {
    g.setColor(background);
    g.fillRect(0, 0, width, height);
   }
  
   paint(g);
  }
 
  public void paint(Graphics g)
  {
  }
  ...
 }

Davon erbt ein GameImageObject, welches direkt in der Lage ist ein Image zu zeichnen

Code:
 public class GameImageObject extends GameObject
 {
  Image image;
  ...
  public void paint(Graphics g)
  {
   g.drawImage(image, 0, 0, width, height, null);
  }
  ...
 }

Nun gibt es noch ein weiteres Objekt, welches sozusagen das Spielbrett darstellt. Es merkt sich eine Menge von GameObject - Instanzen und zeichnet diese, wenn sie sich im Sichtfeld befinden.

Code:
 public class Board extends GameObject
 {
  ...
  public boolean isVisible(Point p)
  {
   if (p.getX() < posX + offX || p.getX() > posX + width + offX)
    return false;
   if (p.getY() < posY + offY || p.getY() > posY + height +offY)
    return false;
    
   return true;
  }
 
  public boolean isVisible(Rectangle r)
  {
   if (isVisible(new Point((int)r.getX(), (int)r.getY())))
    return true;
   if (isVisible(new Point((int)r.getX() + (int)r.getWidth(), (int)r.getY())))
    return true;
   if (isVisible(new Point((int)r.getX(), (int)r.getY() + (int)r.getHeight())))
    return true;
   if (isVisible(new Point((int)r.getX() + (int)r.getWidth(), (int)r.getY() + (int)r.getHeight())))
    return true;
   
   return false;
  }
 
  public boolean isVisible(GameObject go)
  {
   return isVisible(go.getRectangle());
  }
 
  public void paint(Graphics g)
  {
   Graphics gx = g.create(0, 0, width, height);
 
   for (int i=0;i<objects.size();i++)
   {
    GameObject go = objects.get(i);
   
    if (isVisible(go))
     go.paint(gx.create(go.getPosX() - offY, go.getPosY() - offY, go.getWidth(), go.getHeight()));
   }
  }
  ...
 }

Das ganze teste ich nun mit einem JFrame, wobei die Instanz von Board eigentlich zunächst in ein BufferedImage zeichnen sollte...


Code:
 public class Frame1 extends JFrame
 {
  Board gameBoard;
  BufferedImage img;
  ...
  public void paint(Graphics g)
  {
   Insets ins = getInsets();
   Graphics gx = g.create(ins.left, ins.top, getWidth() - ins.left - ins.right, getHeight() - ins.top - ins.bottom);
  
   gameBoard.paint(gx);
  }
 
  public void update(Graphics g)
  {
   // DoubleBuffering...
   Graphics gx = img.createGraphics();

   // dieser blaue Hintergrund kommt manchmal flickernd zum Vorschein, obwohl das zeichnen ja eigentlich
   // im BufferedImage stattfindet und beim zeichnen des images das blau gar nicht mehr zu sehen sein dürfte
   gx.setColor(new Color(0,0,255));
   gx.fillRect(0, 0, getWidth(), getHeight());

   paint(gx);
  
   g.drawImage(img, 0, 0, null);
  }
  ...
  public static void main(String[] args)
  {
   ...

   // repaint Thread
   new Thread()
   {
    JFrame frame;
   
    public void run()
    {
     while (true)
      frame.repaint();
    }
   
    public Thread init(JFrame frame)
    {
     this.frame = frame;
    
     return this;
    }
   }.init(test).start();

   // scroll Thread
   new Thread()
   {
    Board board;
   
    public void run()
    {
     long lastTick = System.currentTimeMillis();
     int step = 15;
     
     while (true)
     {
      if (System.currentTimeMillis() - lastTick > step)
      {
       lastTick += step;
      
       int x = board.getOffX();
       int y = board.getOffY();
     
       x++;
       if (x >= 32)
        x = 0;

       y++;
       if (y >= 32)
        y = 0;
       
       board.setOffX(x);
       board.setOffY(y);
      }
     }
    }
   
    public Thread init(Board board)
    {
     this.board = board;
    
     return this;
    }
   }.init(gameBoard).start();
   ...
  }
 }

Dort gibt es zwei Threads... einer, der in regelmäßigen Abständen das offset des Boards verändert und so die enthaltenen Objekte scrollt und ein anderer, welcher immer wieder repaint() aufruft.

Wer es mal selbst ausprobieren möchte:

http://www.egoshare.com/7017bd0f997c0add3da67c4c2b0746b8/bombermanzip.html

Am lustigsten finde ich, dass das Programm auf meinem Pentium IV 100% CPU Last verursacht und auf nem Core 2 Duo T5500 gerade 6-7% Auslastung beider Kerne hervorbringt...

Ausserdem finde ich, dass das zeichnen dieser paar Objekte ruhig etwas flüssiger sein könnte... Wo kann man da was verbessern?
 

Wildcard

Top Contributor
Das ist kein Applet, sondern eine Applikation.
Das war mal ein Haufen Arbeit umsonst. Wenn du vorher etwas Literatur gelesen hättest, dann wüsstest du das JFrame Swing ist, und Swing bereits doppelt gepuffert ist.
Ich kann dir nur sehr davon abraten update zu überschreiben, das macht man in AWT.
Deine while Schleife musst du auch ändern. Du musst da ein sleep einbauen, sonst verbrätst du zu viele Resourcen.
 

moormaster

Top Contributor
Wildcard hat gesagt.:
Das ist kein Applet, sondern eine Applikation.

Hab ich im letzten Moment auch noch gemerkt :D

Das war mal ein Haufen Arbeit umsonst. Wenn du vorher etwas Literatur gelesen hättest, dann wüsstest du das JFrame Swing ist, und Swing bereits doppelt gepuffert ist.

Das heisst wenn ich nur paint überschreibe, habe ich automatisch eine Doppelpufferung in Swing?

Kann mir das auch Performance beim Zeichnen klauen, wenn ich in Swing anstatt in AWT zeichne?

Ich kann dir nur sehr davon abraten update zu überschreiben, das macht man in AWT.
Deine while Schleife musst du auch ändern. Du musst da ein sleep einbauen, sonst verbrätst du zu viele Resourcen.

Scheint sogar flüssiger zu werden, wenn ich ein Thread.sleep(step) im scroll thread nehme anstatt das über die Systemzeit zu synchronisieren... Der repaint-Thread soll aber durchaus so schnell wie möglich neu zeichnen... da nehme ich dann auch eine hohe Auslastung in Kauf.

Nur komisch, dass der Core 2 Duo sich dabei vorher ausgeschlafen hat und erst jetzt wo ich das Thread.sleep im Scroll-Thread mit drin hat, gibts da auch ne richtige Auslastung :D
 

Wildcard

Top Contributor
Ich empfehle dir nicht paint zu überschreiben, sondern ein JPanel auf den JFrame zu adden und dort paintComponent zu überschreiben.
 

moormaster

Top Contributor
Wildcard hat gesagt.:
Ich empfehle dir nicht paint zu überschreiben, sondern ein JPanel auf den JFrame zu adden und dort paintComponent zu überschreiben.

Hab auf dem P4 ungefähr die Hälfte CPU Last, wenn ich in ein Frame mit selbst implementiertem DoubleBuffering anstatt in ein JFrame zeichne... Was wäre in diesem Fall Deine Empfehlung, wenn ich nicht paint des Frames überschreiben soll?

Hab es soweit versucht in ein Panel (welches einem Frame hinugefügt wurde) zu zeichnen... nur leider bewirkt [Frame].repaint() nicht, dass das Panel immer wieder neu gezeichnet wird. Statt dessen wird es nur einmal gezeichnet und dann immer nur die Stellen, welche z.B. durch andere Fenster verdeckt wurden.

Des weiteren gibt es im Panel keine paintComponent Methode (die gibts ja nur im JPanel) also musste ich dort die paint Methode überschreiben.
 

Wildcard

Top Contributor
Ich hab ja auch JPanel gesagt.
Zum ständigen neuzeichnen kannst du einen Thread der auf dem JPanel repaint aufruft und anschließend x Millisekunden schläft.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
K Flackern bei repaint Methode Spiele- und Multimedia-Programmierung 3
J Flackern bei Animationen Spiele- und Multimedia-Programmierung 6
Seikuassi LWJGL - Texturen flackern Spiele- und Multimedia-Programmierung 2
D Objekte in weiter Entfernung flimmern / flackern Spiele- und Multimedia-Programmierung 2
D 2D FireFighter, Problem mit Flackern Spiele- und Multimedia-Programmierung 5
M Seltsames Flackern bei Laden von Grafiken Spiele- und Multimedia-Programmierung 4
A Bilder flackern Spiele- und Multimedia-Programmierung 5
S [LWJGL] Zweimal selbe Textur trotz unterschiedlicher IDs Spiele- und Multimedia-Programmierung 3
A Trotz Antialiasing zu verpixelt Spiele- und Multimedia-Programmierung 13
S Spiel ruckelt trotz 50 fps Spiele- und Multimedia-Programmierung 16
Devil0s Spiel laggt trotz 90 FPS (bei der Anzeige) Spiele- und Multimedia-Programmierung 9
V Jogl: Objekt trotz Rotation immer in gleiche Richtung bewegen Spiele- und Multimedia-Programmierung 5
M Ich bekomme 2 unterschiedliche Kreise trotz gleiche Methodik Spiele- und Multimedia-Programmierung 8
egrath [Java3D] Keine Darstellung trotz Geometrie und Licht Spiele- und Multimedia-Programmierung 6
B Java3D Klassen können trotz Installation nicht benutzt werde Spiele- und Multimedia-Programmierung 6
K Rotate in DoubleBuffering Spiele- und Multimedia-Programmierung 2

Ähnliche Java Themen

Neue Themen


Oben