JViewPort Ausschnitt skalieren

Senda

Mitglied
Guten Tag,

ich in aktuell dabei ein Spiel zu Programmieren. Dazu habe ich ein JPanel erstellt in der Größe 5760x2160 in der befinden sich z.B. ein Hintergrundbild, Grafiken und dort sind auch Methoden, die das Spiel betreffen. Zum Beispiel kann eine Spielfigur (PNG Bild) über das Spielfeld bewegt werden. Das JPanel soll so gelassen werden, da sich Berechnung anhand der Größe errechnen.

Je nach "Spielgeschehen" soll ein bestimmter Auschnitt des JPanels gezeigt werden. Zum Beispiel wenn sich eine Spielfigur nach links bewegt soll der Ausschnitt auch nach links wandern. Die Höhe des Ausschnitts ist immer 1080 Pixel und die Breite richtet sich nach dem Bildschirmformat. Also z.B. bei 16:9 ist die Breite 1920 Pixel.

Dies habe ich aktuell mit einem JViewport realisiert, welches in einem JFrame angezeigt wird. Über setView habe ich das JPanel übergeben, mit setExtentSize die Größe des Ausschnitts gewählt und über setViewPosition die Position des Ausschnittes.


Nun habe ich jedoch ein Problem. Wenn das JFrame nun kleiner ist als 1920x1080, dann müsste das was im JViewPort angezeigt wird dementsprechend runterskaliert werden. Also nicht die Größe des Ausschnittes vom JPanel reduzieren, sondern das was "in JViewPort ist" muss auf die Größe des JFrames runterskaliert werden.

Wie bekomme ich dies realisiert?
Würde dies mit JScrollPane gehen (wenn ja, wie?). Hatte mich für JViewPort entschieden, da der Benutzer ja nicht scrollen soll, sondern der Ausschnitt durch das Spielgeschehen bestimmt wird.

Schon mal vorab, vielen Dank für die Hilfe
 

Senda

Mitglied
Also ich verstehe jetzt nicht genau wie mir das weiterhelfen soll.
Die Darstellung klappt ja bereits. JViewport nimmt sich den gewünschten 1920 x 1080 Ausschnit aus dem JPanel. Jedoch muss dieser ja noch auf die JFrame größe runter skaliert werden können. Wie soll das funktionieren :D ?
 

kaoZ

Top Contributor
Du solltest du in der ScrollPane den gewünschten bereich darstellen können ( x,y koordinaten ) wenn du die Grafik natürlich noch runterskalieren möchtest,

versuchs mal mit hiermit:

BufferedImage.getScaledInstance();


ansonsten hab ich auf die Schnelle das hier gefunden :

Image Scalling Java

Java:
public class ImageScaler {

    public BufferedImage scaleImage(BufferedImage img, Dimension d) {
        img = scaleByHalf(img, d);
        img = scaleExact(img, d);
        return img;
    }

    private BufferedImage scaleByHalf(BufferedImage img, Dimension d) {
        int w = img.getWidth();
        int h = img.getHeight();
        float factor = getBinFactor(w, h, d);

        // make new size
        w *= factor;
        h *= factor;
        BufferedImage scaled = new BufferedImage(w, h,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g = scaled.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        g.drawImage(img, 0, 0, w, h, null);
        g.dispose();
        return scaled;
    }

    private BufferedImage scaleExact(BufferedImage img, Dimension d) {
        float factor = getFactor(img.getWidth(), img.getHeight(), d);

        // create the image
        int w = (int) (img.getWidth() * factor);
        int h = (int) (img.getHeight() * factor);
        BufferedImage scaled = new BufferedImage(w, h,
                BufferedImage.TYPE_INT_RGB);

        Graphics2D g = scaled.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(img, 0, 0, w, h, null);
        g.dispose();
        return scaled;
    }

    float getBinFactor(int width, int height, Dimension dim) {
        float factor = 1;
        float target = getFactor(width, height, dim);
        if (target <= 1) { while (factor / 2 > target) { factor /= 2; }
        } else { while (factor * 2 < target) { factor *= 2; }         }
        return factor;
    }

    float getFactor(int width, int height, Dimension dim) {
        float sx = dim.width / (float) width;
        float sy = dim.height / (float) height;
        return Math.min(sx, sy);
    }
}
 
Zuletzt bearbeitet:

Senda

Mitglied
Also irgendwie stehe ich glaube ich mal wieder auf dem Schlauch sry :D.
Also ich habe hier meine Klasse panView die erbt von JViewPort und bekommt die Klasse panGame (erbt von JPanel übergeben). panGame enthält mehrere Grafiken und hat eine größe von 5760x2180.
Es wird sich bei der oberen linken Pixel bei 1920.1080 das 1920x1080 große Feld genommen und in JViewPort genommen. Was muss ich nun genau machen um dieses auf einem JFrame darzustellen, dass nur 60% der Größe hat, denn panGame soll unverändert bleiben und wie kann ich dann nun in JViewPort mit BufferedImage arbeiten?

Java:
public class PanView extends JViewport {
    private PanGame panGame;

    public PanView(){
        panGame = new PanGame();


        setLayout(null);
        setView(panGame);
        setExtentSize(new Dimension(1920, 1080)); // Größe des Ausschnittes der gezeigt wird
        setViewPosition(new Point(1920, 1080));

    }

}
 

kaoZ

Top Contributor
panGame enthält mehrere Grafiken und hat eine größe von 5760x2180.
Es wird sich bei der oberen linken Pixel bei 1920.1080 das 1920x1080 große Feld genommen und in JViewPort genommen. Was muss ich nun genau machen um dieses auf einem JFrame darzustellen, dass nur 60% der Größe hat,

die Grafiken Skalieren ?!

Wie schon gesagt wenn du Grafiken hast die Größer sind als der Bereich um diese Darzustellen, schriebst du entweder methoden oder eine UtilityKlasse welche die deine Grafiken skaliert in einer von dir bevorzugten Größe zurückgibt, oder du Verwendest für deine Grafiken ein BufferedImage welches dir es ermöglicht über die Methode .getScaledInstance(); eine Kopie des Bildes in einer von dir gewünschten Größe zu erhalten .

Hier zum Beispiel ist die eigentliche Grafik 1920x1080

runterskalliert zu 400 x 300 , sicher passen die Proportionen nichtmehr, und hier wird schnell skaliert , also leidet die auflösung....

Setz doch einfach mal einer deiner Grafiken hier ein , dann siehtst du was ich meine


Java:
public class Foo extends JPanel{

	BufferedImage img;
	
	public Foo() throws IOException {
		
		/**
		 * Die Originalgrafik ist 1920 x 1080 und wird hier runterskaliert auf 400 x 300 px 
		 */
		
		img = ImageIO.read(new File("F:/Bilder/Dodge.png"));
		Image newImg = img.getScaledInstance(400, 300, BufferedImage.SCALE_FAST);
		
		this.add(new JLabel(new ImageIcon(newImg)));
	}
	
	public static void main(String[] args) throws IOException {
		JFrame f = new JFrame();
		
		f.setSize(600,600);
		f.setLocationRelativeTo(null);
		f.add(new Foo());
		
		f.setVisible(true);
	}
}
 
Zuletzt bearbeitet:

Senda

Mitglied
Das Problem was ich habe ist, dass die Grafiken in panGame nicht skaliert werden dürfen , da für Berechnung für das Spielgeschehen das Koordinatensystem, das durch die Hintergrundgrafik (deren Größe) bestimmt wird, entscheidend sind. Es muss also sozuagen ein Ausschnitt (feste Größe) der in panView gewählt wird runterskaliert werden damit er in das JFrame reinpasst aber dabei darf sich in panGame nicht die Größe der Grafiken ändern, da sonst die Spielberechnungen falsch sind. Hoffe du verstehst was ich meine.
 

kaoZ

Top Contributor
Ich fasse schnell zusammen ,

-Du hast Grafiken für ein Game welche Größer sind als der ViewPort bzw. der Panel in welchem sie dargestellt werden.

-Du darfst diese Grafiken nicht skalieren da sie zur Berechnung der Koordinaten dienen

Ok, also hast du nur die möglichkeit den ViewPort entweder durch eine ScrollPane scrollbar zu machen , was hier für spiele denke ich die Falsche Lösung wäre , oder den Frame oder das Panel welches als Container für dein ViewPort dienen dementsprechend groß zu gestalten das der inhalt den du sichtbar machen möchstest auch sichtbar ist .

Bzw. willst du nur einen bestimmten Bereich der eigentlichen Grafik anzeigen , also ein Ausschnitt wie hier im bild :

view-viewport.jpg



Hab ich das soweit nun richtig verstanden ?

[EDIT]also sowas in der Art ? Hier sehr sehr stark vereinfacht xD [/EDIT]

Java:
public class Foo extends JViewport{
	
	public Foo() throws IOException {
		
		JPanel panel = new JPanel(new BorderLayout());
		panel.setPreferredSize(new Dimension(400,200));
		panel.add(new JLabel(new ImageIcon(ImageIO.read(new File("F:/Bilder/Dodge.png")))));
		
		setSize(100,200);
		setView(panel);
		setViewPosition(new Point(20,10));
	}
	
	public static void main(String[] args) throws IOException {
		JFrame f = new JFrame();
		
		f.setBounds(200,400,600,600);
		f.setLayout(null);
		f.setLocationRelativeTo(null);
		f.add(new Foo());
		
		f.setVisible(true);
	}
}

Der eigentliche Panel ist hier 400x200 px , der Viewport stellt aber nur 100x200px zur verfügung, die Grafik ist unverändert in ihrer Größe
 
Zuletzt bearbeitet:

Senda

Mitglied
Jop, hast du richtig verstanden.

Die Option, dass ich mein JFrame dementsprechend groß mache klappt aber leider auch nicht. Weil wenn ich zum Beispiel nen Bildschirm habe der nur 1280x720 groß ist, dann könnte der 1920x1080 große Spielbereich ja niemals dargestellt werden.

Habe hier mal ne Zeichnung mit Pain gemacht. Ich hoffe es ist verständlich

unbenannt8x5bnkiecy.png
 
Zuletzt bearbeitet:

Senda

Mitglied
Kurze Erklärung zum oberen Bild.

Das JPanael ist mein Spielfeld, davon wird je nach Spielgeschehen ein bestimmter Ausschnitt mit JViewPort gezeigt. Dieser Ausschnitt hat eine feste Größe, hier jetzt 1920x1080.

Dieser Ausschnitt in JViewPort muss nur für kleinere Bildschirme runterskaliert werden können, damit er auch vollständig im JFrame angezeigt werden kann
 

kaoZ

Top Contributor
Das Problem ist das du nicht den JViewPort skalieren musst sondern das was der JViewPort darstellt, und das ist in deinem Fall nun mal die Grafik.

Klar kannst du den ViewPort dazu bringen nur einen Bestimmten ausschnitt anzuzeigen, dennoch müsstest du wenn du verschiedene Auflösungen verwenden möchtest die genutzte Grafik dementsprechend runterskalieren,

ich bin mir nicht ganz sicher aber ich denke mal du wirst nicht drum herum kommen die Koordinaten dementsprechend der skalierten Grafik anzupassen bzw. umzurechnen, ich wüsste zumindest jetzt auf die schnelle keine Möglichkeit anhand einer skalierten Grafik, die Originalgröße der Grafik zum berechnen der Koordinaten zu verwenden.

Grafik 5760 x 2160 - Spielwelt

der Nutzer sieht 1920 x 1080 - Vollbild

Du meinst, was passiert nun wenn der Nutzer eine geringe Auflösung nutzt richtig ?

Und diese soll dann automatisch dein ViewPort und die dahinter liegende Grafik dementsprechend anpassen , wie in deinem Beispiel gezeigt , richtig ?
 

Senda

Mitglied
Genau, weil aktuell wird dann einfach der obere linke Teilblock (1280x720) von meinem 1920x1080 großen Spielfeld angezeigt.


Hm also Spielfeld zu ändern wäre echt die schlechteste Möglichkeit, weil dadurch müssten alle Berechnungen für das setzten von Figuren, Bewegungen die Physik abhängig sind und so weiter abgeändert werden.

Gibt es nicht irgendeine Alternative. z.B. das aus der Spielewelt Bild erzeugt wird, dass alles darstellt, und dieses könnte ich dann runterskalieren und den entsprechenden Ausschnitt anzeigen oder so.
 

kaoZ

Top Contributor
Du darfst nicht vergessen du musst auch die Figur selbst etc. runterskallieren , sonst hast du nachher Godzilla der durch ne Miniaturstadt rennt ;)

du musst die Berechnungen nicht ändern sondern lediglich Methoden schreiben die je nach Auflösung die Koordinaten umrechnen, und der Skallierten Grafik anpassen .
 
Zuletzt bearbeitet:

Senda

Mitglied
Hm dann werd ich mich die Woche mal da dran setzten, hatte eigentlich gehofft es gibt ne schönere Methode aber bleibt wohl keine andere Wahl.

Vielen Dank für deine Hilfe
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Swing JViewPort, Absolut Koordinaten berechnen. AWT, Swing, JavaFX & SWT 2
B Swing JViewport Problem AWT, Swing, JavaFX & SWT 4
T Repaint funktioniert nicht über JViewPort AWT, Swing, JavaFX & SWT 2
B JScrollPane.getComponent(0) -> JViewport, warum? AWT, Swing, JavaFX & SWT 3
M Probleme mit JViewport.setViewPosition(Point)... AWT, Swing, JavaFX & SWT 4
0 Ausschnitt eines JPanels als Bild speichern AWT, Swing, JavaFX & SWT 4
C JFreeChart X-Achse Werte skalieren, begrenzen, zoomen AWT, Swing, JavaFX & SWT 5
berserkerdq2 Skalieren sich javafx objekte automatisch auf die Bildschirmgröße AWT, Swing, JavaFX & SWT 6
C Swing ImageIcon erstellen, skalieren und verwenden AWT, Swing, JavaFX & SWT 3
U Was genau ist skalieren bei 2dGraphics? AWT, Swing, JavaFX & SWT 4
S Bild neu skalieren - Bild in Bild speichern? AWT, Swing, JavaFX & SWT 6
J JavaFX JavaFX Elemente an Fenstergröße skalieren AWT, Swing, JavaFX & SWT 5
E Bilder skalieren AWT, Swing, JavaFX & SWT 4
B Swing JTextField mit Bildschirmauflösung skalieren lassen. AWT, Swing, JavaFX & SWT 4
D LayoutManager GUI skalieren und deren Komponenten mit Grid(Bag)Layout-Manager. AWT, Swing, JavaFX & SWT 5
A Bild in JLabel skalieren AWT, Swing, JavaFX & SWT 4
L 2D-Grafik Avatar skalieren und zuschneiden. AWT, Swing, JavaFX & SWT 9
S Bild skalieren AWT, Swing, JavaFX & SWT 3
C LayoutManager Grafik soll nicht im GridLayout Skalieren AWT, Swing, JavaFX & SWT 3
A JFrame skalieren AWT, Swing, JavaFX & SWT 2
F 2D-Grafik Skalieren der Scrollbars beim Zoomen einer JScrollPane AWT, Swing, JavaFX & SWT 4
P Swing Bild an Fenstergröße skalieren AWT, Swing, JavaFX & SWT 11
S AWT Skalieren von Polygon über Area klappt nicht AWT, Swing, JavaFX & SWT 4
N 2D-Grafik Panelgrafik im nachhinein skalieren AWT, Swing, JavaFX & SWT 4
C GUI-Komponenten skalieren AWT, Swing, JavaFX & SWT 10
B Fenstergröße automatisch skalieren AWT, Swing, JavaFX & SWT 7
B Bild skalieren AWT, Swing, JavaFX & SWT 2
N JFreeChart: Plot soll mit skalieren AWT, Swing, JavaFX & SWT 5
Q 2D-Grafik Shape skalieren AWT, Swing, JavaFX & SWT 5
D BufferedImage Größe skalieren AWT, Swing, JavaFX & SWT 2
P Swing Skalieren mit DrawImage macht Linien kaputt AWT, Swing, JavaFX & SWT 6
C Image performant skalieren AWT, Swing, JavaFX & SWT 5
R Bild drehen UND skalieren (Image bzw BufferedImage) AWT, Swing, JavaFX & SWT 5
DStrohma Bild für TrayIcon skalieren AWT, Swing, JavaFX & SWT 13
N Panel skalieren AWT, Swing, JavaFX & SWT 7
N Swing sehr großes Bild skalieren AWT, Swing, JavaFX & SWT 8
D image skalieren AWT, Swing, JavaFX & SWT 5
K JPanel proportional skalieren AWT, Swing, JavaFX & SWT 7
P [SWT] Background-Image skalieren statt kacheln AWT, Swing, JavaFX & SWT 2
R Bild skalieren und anschließend beschneiden AWT, Swing, JavaFX & SWT 3
J Fixes Layout auf beliebige Fenstergröße skalieren AWT, Swing, JavaFX & SWT 2
I Layout Problem beim Skalieren AWT, Swing, JavaFX & SWT 3
M Schlechte Qualität beim skalieren von Bildern AWT, Swing, JavaFX & SWT 10
S Bild skalieren AWT, Swing, JavaFX & SWT 9
B Bild Skalieren AWT, Swing, JavaFX & SWT 2
I Bild skalieren AWT, Swing, JavaFX & SWT 4
O JFrame JPanelgrösse fixieren Bild darin skalieren AWT, Swing, JavaFX & SWT 2
M BufferedImage skalieren AWT, Swing, JavaFX & SWT 6
S Drucken - Bild skalieren AWT, Swing, JavaFX & SWT 2
I Bilder skalieren => OutOfMemoryError AWT, Swing, JavaFX & SWT 2
M Bild skalieren AWT, Swing, JavaFX & SWT 8
S AWT Frame-Inhalt in Echtzeit skalieren AWT, Swing, JavaFX & SWT 6

Ähnliche Java Themen

Neue Themen


Oben