2D-Grafik BufferedImage Performance

  • Themenstarter Themenstarter Buffered
  • Beginndatum Beginndatum
B

Buffered

Gast
Ich bin vor ein paar Tagen auf ein altes Problem von mir gestossen und will dieses nun entgültig lösen :/

Es geht darum, dass das Zeichnen von größeren BufferedImages (und auch von normalen Images) den CPU des Rechners ziemlich stark auslastet. (Es Geht jetzt wirklich um schwache Rechner wie z.B. welche mit 1.2 GHZ [Hautpsächlich Single-Core])

Hier mal den Code mit dem Gezeichnet wird.
Java:
package javaapplication1;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

/**
 * @author Gast
 */
public class Game extends JPanel implements Runnable{

    private BufferedImage image;
    /**
     * Konstruktor der Game Klasse.
     */
    public Game() {
        this.setDoubleBuffered(true);
        this.setSize(640, 480);
        new Thread(this).start();
        try {
            image = ImageIO.read(new File("./img/640x480ImageMitTransparenz.png"));
        }
        catch (Exception e) {
            //Egal.
        }
    }

    /**
     * Game Schleife
     */
    public void run() {
        while (true) {
            long  start = System.currentTimeMillis();
            repaint();
            long ende = System.currentTimeMillis() - start;

            try {
                if (ende < 40) {
                    //Zeichnet 25 Mal in der Sekunde.
                    Thread.sleep(40 - ende);
                }
            }
            catch (Exception e) {
                //Für das Beispiel uninteressant.
            }
        }
    }

    /**
     * Zeichnen des "Spiels".
     * @param g Aktueller Graphics Objekt
     */
    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawImage(image, 0, 0, this);
        g.dispose();
    }
}

Java:
package javaapplication1;

import javax.swing.JFrame;

/**
 * @author Gast
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame("Test");
        frame.add(new Game());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

Nun Die Frage:
Wieso wird der CPU so Stark ausgelastet?

Und nein, ich will jetzt keine Links zu Slick etc. sondern nur eine Erklärung wieso das so ist und wie man sowas umgehen kann.
Und ja, es ist nötig das Bild so oft zu Zeichnen.

Getestet Wurde übrigens auf Win XP, Win Vista, Win7 und Mac OS X

Schöne Grüße
 
Nicht zuletzt weil es aufwändig ist, Bilder mit Transparenz zu zeichnen. Im konkreten Fall gibt es keinen Grund, das Bild NICHT in ein simples BufferedImage.TYPE_INT_RGB umzuwandeln, was vermutlich deutlich schneller gezeichnet werden könnte. Wenn es für den realen Anwendungsfall Transparenzen enthalten muss, wird die Luft IMHO dünn...
 
Ich habe das gleiche Problem gehabt und bei meinem 2D Spiel (es werden 40 Frames per Sekunde mit durchschnittlich 500 halbtransparenten Bildern gezeichnet) mit VolatileImages gelöst.
Die Performance ist auf PCs mit aktueller Grafikkarte und genügend VRAM sehr gut und das Spiel läuft sehr flüssig.
Bei Computern mit schlechterer Grafikkarte (zum Beispiel mein 2 Jahre altes Netbook) lässt die Performance allerdings zu wünschen übrig und das Spiel läuft sehr ruckelig (so läuft es übrigens auch bei guter Hardware wenn BufferedImages genutzt werden).
Ich habe viel gegoogelt und in Foren geschaut, weiss jedoch nicht wie ich die Kluft schliessen und das Spiel ebenfalls für schwächere Hardware spielbar machen kann.

Für Tipps bin ich sehr dankbar (Macht es eventuell Sinn OpenGL zu verwenden?).

VolatileImages: http://java.sun.com/j2se/1.4/pdf/VolatileImage.pdf
Link zu meinem Spiel: Forgotten Elements Online Action MMORPG
 

Zurück
Oben