Java-TexturePaint sehr langsam

Eichelhäer

Bekanntes Mitglied
Hallo,
ich hab ein JFrame mit nem JPanel und zeichne darin mittels repaint eine 32x32 Kacheln großes isometrisches Spielfeld.
Das ganze wird mit nem transformierten ( AffineTransform) Shape array und nem TexturePaint array im konstruktor erzeugt und anschließend mittels g2.setPaint und g2.fill auf den Bildschirm gerendert. Ich translatiere nun das spielfeld mittels g2.translate und scrolle so die map. Das problem ist, dass das ganze trotz des einmaligen ladens bzw erzeugens sowohl der shapes als auch der texture das ganze sehr stark ruckelt. Ich hab mich durch viele foren gelesen. Vorschläge mit backbuffer oder volatile image etc. brachten gingen auch nicht. Außerdem habe ich mit g2.clip den renderBereich eingeschränkt und in repaint nur den relevanten Bereich zum neuzeichnen angegeben. Ebenso die g2.clearRect Methode. Daher meine Frage ist dieses Texture Paint so "teuer" für die laufzeitumgebung, dass es einfach so ruckelt oder an was liegt das? Ich kann natürlich sehr große TileMaps anzeigen ohne Texture Paint mit der klassischen Methode und render bereich einschränken auch isometrisch. Mich hätte das nur interessiert wie man dieses Texture Paint verstehen soll. Java hat ja in der Standard library sooooo viele sehr nützliche Klassen, es gibt nur zu wenig beispiele für eher unbekannte Klassen.
 
Java:
public void init() {
        
        iso_tile_sprites  = new Sprite("isometric_demo",TILE_SIZE.x,TILE_SIZE.y);
        
        transform = new AffineTransform();
        transform.preConcatenate(AffineTransform.getRotateInstance(Math.toRadians(45.0)));
        transform.preConcatenate(AffineTransform.getScaleInstance(TILE_SIZE.x/2,TILE_SIZE.y/2));
        transform.preConcatenate(AffineTransform.getTranslateInstance(width/2,0));
        
        shape = new Shape[WORLD_SIZE.x*WORLD_SIZE.y];
        
        for(int y = 0; y < WORLD_SIZE.y; y++) {
            for(int x = 0; x < WORLD_SIZE.x; x++) {
                shape[y*WORLD_SIZE.x+x] = transform.createTransformedShape(new Rectangle2D.Double(x,y,1,1));
            }
        }
        
        tp = new TexturePaint[WORLD_SIZE.x*WORLD_SIZE.y];
        
        for(int y = 0; y < WORLD_SIZE.y; y++) {
            for(int x = 0; x < WORLD_SIZE.x; x++) {
                tp[y*WORLD_SIZE.x+x] = new TexturePaint(iso_tile_sprites.getSpriteImage(--mapdata[y*WORLD_SIZE.x+x]),shape[y*WORLD_SIZE.x+x].getBounds2D());
            }
        }
    }

@Override
    public void paint(Graphics g) {
        super.paint(g);
        
        Graphics2D g2 = (Graphics2D) g;
        
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        g2.setBackground(Color.black);
        g2.clearRect(0,0,width,height);
        
        g2.clipRect(0,0,width,height);
        
        g2.translate(offset.x,offset.y);
        
        for(int y = 0; y < WORLD_SIZE.y; y++) {
            for(int x = 0; x < WORLD_SIZE.x; x++) {
                g2.setPaint(tp[y*WORLD_SIZE.x+x]);
                g2.fill(shape[y*WORLD_SIZE.x+x]);
            }
        }
        
        g2.translate(-offset.x,-offset.y);
        
        g2.setClip(null);
        
        g2.dispose();
    }

Der Rest ist einfach der offset mittels Tasten die geupdated werden und ein JFrame mit JPanel als content pane und natürlich eine rudimentäre spielschleife.
 
Ich muss dazu sagen, dass ich hier die kachelkoordinaten im rec2d erzeugt habe. Die Laggs entstehen aber auch bei der erzeugung von screen koordinaten.
 
Und der renderbereich ist bei dieser mapgröße nicht eingeschränkt also mit startx endx etc., da die gesamte karte auf dem screen sichtbar ist.
 
Als ersten Schritt - gibt es einen Grund, das du paint und nicht paintComponent überschreibst? In der Regel sollte man in Swing Anwendungen paintComponent überschreiben. Sollte aber nicht wirklich was ausmachen.

Beim lesen der Doku bin ich aber auf folgendes gestoßen:
The size of the BufferedImage object should be small because the BufferedImage data is copied by the TexturePaint object.
Du erzeugst WORLD_SIZE * WORLD_SIZE TexturePaint Objekte.

Frage: Wie groß ist WORLD_SIZE? Wie groß sind die Sprites? Evtl. läufst du einfach in Speicherprobleme rein.
 
Die WORLD ist 32x32 Kacheln groß das hatte ich bereits geschrieben. Die BufferedImages also die Textur is 40x20 pixel groß. Ist nur ein sehr kleine Spritesheet mit 12 Isometrischen Texturen.
 
Zum active rendering: Ich hatte es auch mit ner Canvas und ner Bufferstrategy versucht mit 3 Buffern (siehe oracle active rendering tutorial),allerdings isses da dasgleiche. Ich denke das das mit diesem Graphics objekt und dieser texture Paint Klasse zusammenhängt, denn wie bereits erwähnt kann ich Welten mit derselben Textur der Größe 3200x3200 zeichnen und alles läuft flüssig. Hier nehme ich dann zum zeichnen der Textur eben die drawImage methoden was ohne probleme funktioniert. Ich möchte nur mal was anderes versuchen und mir eben diese Graphics2D Klasse mal genauer ansehen rein Interessehalber. Ich komme außerdem ganz gut klar mit dieser AffineTransform klasse und ein Isometrisches spielfeld ist ja nicht anderes als ein um 45 Grad gedrehtes und translatiertes grid aus einzelnen tiles, die man im verhältnis 2:1 skalieren kann, um einen schönen isometrichen effekt zu erhalten. Klar das ganze geht mit opengl und 3 dimensionalen vektoren eventuell besser und präziser, ist aber nicht unbedingt einfacher, wenn man mit opengl noch nicht so viel erfahrung hat. Texture Paint enthält auch die klasse createContext allerdings bin ich dabei ratlos.
 

Neue Themen


Zurück
Oben