2D-Grafik Im 2D Spiel zoomen

Trunk

Mitglied
Hallo!

Zur Zeit bin ich dabei, ein kleines 2D-Spiel mit Java zu programmieren. Die gesamte Welt besteht aus "Tiles", momentan nur 64 x 64 Pixel große Grastexturen, welche aneinandergereiht sind und so eine Fläche bilder. Jedes dieser Tiles ist ein eigenes Objekt.

Nun wollte ich eine Funktion einbauen, welche es ermöglicht über das Maussrad rein bzw raus zu zoomen.



Java:
final Dimension panelSize = parent.getSize();
            final int width = panelSize.width;
            final int height = panelSize.height;
	    	
            final int imageWidth = 
                    (int) (pics[currentpic].getWidth() * parent.getZoomfactor());
                final int imageHeight = 
                    (int) (pics[currentpic].getHeight() * parent.getZoomfactor());
                final int imageX = width / 2 - imageWidth / 2;
                final int imageY = height / 2 - imageHeight / 2;
                final Image image = pics[currentpic].getScaledInstance(
                        imageWidth, imageHeight, Image.SCALE_SMOOTH);

Das hier ist grundsätzlich mal der Code, mit dem ich versucht habe jedes einzelne Objekt zu skalieren, was jedoch einfach nicht so gut geklappt hat, beziehungsweise wahrscheinlich viel zu umständlich ist.
Gibt es irgendeine möglichkeit, einfach den gesamten Inhalt des JPanels zu skalieren?

Wie sollte ich so eine Zoom-Funktion am besten implementieren?

Danke schonmal!
 
Kommt drauf an... Wo stand denn der Code? Hoffentlich nicht in der paintComponent...

"Einfach" wäre es, indem man vor dem Zeichnen einen Skalierungsfaktor setzt
Java:
public void paintComponent(Graphics gr)
{
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)gr;

    g.scale(1.234, 1.234);
    ... // Normal weiterzeichnen
}

Ggf. muss man schauen, dass es mit der Verschiebung der Karte dann noch passt, aber vom Prinzip her.

Durch das skalierte Zeichnen kann es aber (meistens nur ein bißchen, aber manchmal leider sehr deutlich) langsamer werden. Dann KÖNNTE man in Erwägung ziehen, z.B. nur während des Zoomens größere/kleinere Bilder zu erstellen, und die dann UNskaliert zu zeichnen. Kann aber auch aufwändig werden (speziell wenn es nicht nur um Bilder geht). Eine "Silver Bullet" für's skalierte Zeichnen kenne ich also auch nicht...
 
Kommt drauf an... Wo stand denn der Code? Hoffentlich nicht in der paintComponent...

"Einfach" wäre es, indem man vor dem Zeichnen einen Skalierungsfaktor setzt
Java:
public void paintComponent(Graphics gr)
{
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)gr;

    g.scale(1.234, 1.234);
    ... // Normal weiterzeichnen
}

Ggf. muss man schauen, dass es mit der Verschiebung der Karte dann noch passt, aber vom Prinzip her.

Durch das skalierte Zeichnen kann es aber (meistens nur ein bißchen, aber manchmal leider sehr deutlich) langsamer werden. Dann KÖNNTE man in Erwägung ziehen, z.B. nur während des Zoomens größere/kleinere Bilder zu erstellen, und die dann UNskaliert zu zeichnen. Kann aber auch aufwändig werden (speziell wenn es nicht nur um Bilder geht). Eine "Silver Bullet" für's skalierte Zeichnen kenne ich also auch nicht...

Nein, also der Code stand in der DrawObjects Methode der einzelnen Objekte.
Ich werde einfach nochmal weiter rumprobieren, ich dachte nur dass es vielleicht eine einfachere Möglichkeit gäbe als jedes Objekt einzeln zu skalieren...

Edit:

Ich verwende jetzt folgenden Code um die Tiles und den Charakter zu skalieren:

Java:
 Graphics2D g2 = (Graphics2D)g;
	        int newW = (int)(image.getWidth() * world.getZoomfactor());
	        int newH = (int)(image.getHeight() * world.getZoomfactor());
	        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
	                            RenderingHints.VALUE_INTERPOLATION_BILINEAR);
	        g2.drawImage(image, x-scrollx, y-scrolly, newW, newH, null);

Das klappt soweit auch sehr gut, nur suche ich jetzt nach der Formel, welche die Tiles der Welt richtig verschiebt, aktuell sieht das ganze nämlich wie folgt aus:







Die einzelnen Teile werden also größer, haben dann aber natürlich keinen Platz mehr. Mir ist klar dass ich die x und y Koordinaten irgendwie ändern muss, ich komm jedoch nicht auf die Lösung ???:L
 
Zuletzt bearbeitet:
Ist schwer, das richtig einzuordnen, ohne mehr Code (und MIT mehr Code müßte man den erstmal nachvollziehen), aber irgendwo wirst du vermutlich die x- und y-Position (bzw. die Verschiebung) durch world.getZoomfactor() teilen müssen...
 
Ich denke mal dass es irgendwie so sein müsste dass die Tiles die sich näher am Spieler und damit mehr in der Bildschirmmitte logischerweise weniger bewegen dürften als die am Rand, da der Spieler sich ja auch beim zoomen noch auf demselben Tile befinden sollte, wie mans genau umsetzt, darauf bin ich aber leider noch nicht gekommen... ???:L
 
Wie organisierst du denn die Tiles? Ich habe dafür eine eigene "Map" Klasse gebaut (in meinem ewig unfertigem tile-based-game^^). Wenn du weißt, auf welchem Tile sich deine Spielfigur gerade befindet, kannst du dort anhand des Zoom-Faktors berechnen, wie viele weitere Tiles gerade angezeigt werden müssen und diese dann zum Zeichnen anregen. (Eine solche Verwaltung hat den Vorteil, dass du auch andersartige Tiles leichter hinzufügen könntest).

Sagen wir der Zoom Faktor ist 2, du hast also reingezoomt, und dein Bild ist 800 px breit. Deine Spielfigur befindet sich in x-Richtung auf Pos. 460 (mit ihrem Mittelpunkt). Da ich davon ausgehe, dass bei 0,0 das erste Tile beginnt, befindet sich die Figur 12 px vom linken Rand des aktuellen Tiles (460%64). Also muss das Tile in der Mitte die x-Position 400 - 12*2 haben und das Tilelinks die Position 400-12*2 - 64*2. Das noch weiter links logischerweise 400-12*2 - 2*(64*2) und so weiter...
 
Also ich habe es jetzt geschafft, die Formel für die x&y Verschiebung der Tiles war:

Java:
 double xdistance = this.x - world.p.getX();
	        double xChange = xdistance * (1-world.getZoomfactor());
	        
	        double ydistance = this.y - world.p.getY();
	        double yChange =  ydistance * (1-world.getZoomfactor());
den Wert musste man von der der Position des Objekts abziehen und voila, es hat geklappt.
 

Zurück
Oben