D
Des
Gast
Hallo!
Ich möchte gerne ein 2D-Strategiespiel programmieren und scheitere gerade an der Performance der GUI. Zur Einordnung: Im Moment funktioniert alles, es ist nur zu langsam.
Problemstellung: Ich habe viele Bilder 64x64 mit transparenten Texturen. Diese liegen zur Zeit alle im .png Format vor. Im groben werden diese 64x64 Bilder nun aneinandergepflastert und ergeben damit eine Landkarte. Je nach Spielfortschritt ändern sich aber Kleinigkeiten an den Texturen (Rohstoffe wurden erschlossen), sodass aktuell ein 64x64 Tile mit einem anderen überlagert wird, wenn der Spielfortschritt es erfordert. Man sieht dann also ein zum größten Teil transparentes 64x64 Bild über dem 64x64 Grundfeld liegen. Je nach Spielverlauf sind das viele Bilder übereinander (~10 Stück). Der Benutzer sieht nun einen Ausschnitt der Landkarte und die Karte soll scollbar sein.
Aktuelle Lösung (bitte nicht steinigen): Ich benutze ein JScollPane auf dem die gesamte Karte liegt. Dieses JScrollPane wird verschoben, wenn sich die Maus in einem definierten Bereich befindet. Meine Landkarte ist datenstrukturtechnisch in einem 2D-Array von 64x64 Feldern gespeichert und jeder Eintrag der Matrix steht für ein 64x64 Feld.
Immer, wenn sich aufgrund der Spielsituation etwas an der Darstellung der Karte ändert, rufe ich updateImage() auf den sich verändernden Feldern auf. Diese Methode macht eine deepCopy vom eigentlichen Grundfeld und fügt dieses mit den ganzen überlagernden Bildern mittels mergeImage() zusammen und speichert das fertige Image als Datenfeld in der Matrix. Je nachdem, was da noch so auf der Karte ist, muss ich manchmal noch eine schwarze Linie einzeichnen:
Jedes dieser 64x64 Felder kennt also sein aktuelles Bild, was die GUI anzeigen soll. Wenn nun das JScrollPane verschoben wird, male ich den aktuell sichtbaren Bereich neu.
Wie genau? Meine Landkarte liegt auf einem JPanel. Dieses JPanel ist aud dem JScrollPane. Ich arbeite mit einem OffscreenImage (buffering). ich habe PaintComponent meiner Landkarte wie folgt überschrieben:
Was macht nun paintBuffer? Es geht alle Felder, die neu sichtbar sein sollen durch und malt alle Bilder: (Für alle x,y, die sichtbar sind: (das sind aktuell ca. 100 Stück, sollen aber mal deutlich mehr werden))
Problem: Je nach Leistungsfähigkeit des Computers dauert das Scrollen sehr lange. Wieso? Keine Ahnung! Ist der Ansatz zu langsam oder habe ich irgendwo einen Fehler drin?
Problem 2: Die schwarzen Linien, die ich male sind nicht immer schwarz, manchmal werden sie aus irgendeinem Grund in einer Farbe eines speziellen Pixels der fertigen 64x64 Bilder gezeichnet.
Soweit die Beschreibung, ich höre mal auf, sonst liest es sich niemand mehr durch.
Danke!
Ich möchte gerne ein 2D-Strategiespiel programmieren und scheitere gerade an der Performance der GUI. Zur Einordnung: Im Moment funktioniert alles, es ist nur zu langsam.
Problemstellung: Ich habe viele Bilder 64x64 mit transparenten Texturen. Diese liegen zur Zeit alle im .png Format vor. Im groben werden diese 64x64 Bilder nun aneinandergepflastert und ergeben damit eine Landkarte. Je nach Spielfortschritt ändern sich aber Kleinigkeiten an den Texturen (Rohstoffe wurden erschlossen), sodass aktuell ein 64x64 Tile mit einem anderen überlagert wird, wenn der Spielfortschritt es erfordert. Man sieht dann also ein zum größten Teil transparentes 64x64 Bild über dem 64x64 Grundfeld liegen. Je nach Spielverlauf sind das viele Bilder übereinander (~10 Stück). Der Benutzer sieht nun einen Ausschnitt der Landkarte und die Karte soll scollbar sein.
Aktuelle Lösung (bitte nicht steinigen): Ich benutze ein JScollPane auf dem die gesamte Karte liegt. Dieses JScrollPane wird verschoben, wenn sich die Maus in einem definierten Bereich befindet. Meine Landkarte ist datenstrukturtechnisch in einem 2D-Array von 64x64 Feldern gespeichert und jeder Eintrag der Matrix steht für ein 64x64 Feld.
Immer, wenn sich aufgrund der Spielsituation etwas an der Darstellung der Karte ändert, rufe ich updateImage() auf den sich verändernden Feldern auf. Diese Methode macht eine deepCopy vom eigentlichen Grundfeld und fügt dieses mit den ganzen überlagernden Bildern mittels mergeImage() zusammen und speichert das fertige Image als Datenfeld in der Matrix. Je nachdem, was da noch so auf der Karte ist, muss ich manchmal noch eine schwarze Linie einzeichnen:
Java:
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.BLACK);
if ("blabla") g2d.drawLine(33, 0, 63, 0);
Jedes dieser 64x64 Felder kennt also sein aktuelles Bild, was die GUI anzeigen soll. Wenn nun das JScrollPane verschoben wird, male ich den aktuell sichtbaren Bereich neu.
Wie genau? Meine Landkarte liegt auf einem JPanel. Dieses JPanel ist aud dem JScrollPane. Ich arbeite mit einem OffscreenImage (buffering). ich habe PaintComponent meiner Landkarte wie folgt überschrieben:
Java:
public void paintComponent (Graphics g) {
//this clears the offscreen image, not the onscreen one
offscreenGraphics.clearRect(0, 0, width, height);
//calls the paintbuffer method with
//the offscreen graphics as a param
paintBuffer(offscreenGraphics, g);
//we finaly paint the offscreen image onto the onscreen image
g.drawImage(offscreenImage, 0, 0, null);
}
Was macht nun paintBuffer? Es geht alle Felder, die neu sichtbar sein sollen durch und malt alle Bilder: (Für alle x,y, die sichtbar sind: (das sind aktuell ca. 100 Stück, sollen aber mal deutlich mehr werden))
Java:
public void paintBuffer(final Graphics g, final Graphics onscreenGraphics) {
BufferedImage image = tileMatrix[x][y].getImage();
g.drawImage(image, y * 64 + x % 2 * 32, x * 64, null);
}
Problem: Je nach Leistungsfähigkeit des Computers dauert das Scrollen sehr lange. Wieso? Keine Ahnung! Ist der Ansatz zu langsam oder habe ich irgendwo einen Fehler drin?
Problem 2: Die schwarzen Linien, die ich male sind nicht immer schwarz, manchmal werden sie aus irgendeinem Grund in einer Farbe eines speziellen Pixels der fertigen 64x64 Bilder gezeichnet.
Soweit die Beschreibung, ich höre mal auf, sonst liest es sich niemand mehr durch.
Danke!