Probleme mit AffineTransform

TheChemist

Bekanntes Mitglied
Hallo,
ich programmiere zur Zeit an einem kleinem 2D-Game. Spielfiguren werden dabei durch Rechtecke repräsentiert und sollen mit AffineTransform bewegt werden (nur Translation und Rotation). Das habe ich soweit hinbekommen, bin dabei aber auf ein Problem gestoßen.
So scheint die Transformation lediglich den Umriss des Rechtecks zu verändern. Drehe ich also um 30° und bewege dann ein Stück nach vorne wird das schön gezeichnet, die Koordinaten meines Spielobjektes bzw. Rechtecks bleiben aber unangerührt. Jetzt bin ich bisher erfolglos auf der Suche nach einer Möglichkeit die Koordinaten des Spielobjektes beim transformieren aktuell zu halten. Google und die API habe ich schon heftigst bemüht aber auf keine konkretes Ergebnis gestoßen, vielleicht sehe ich aber auch nur den Wald vor lauter Bäumen nicht mehr^^

Ich habe mal ein kleines Beispiel gecoded, das das Problem nochmal deutlich macht. Das rote Rechteck ist das Spielobjekt vor der Transformation dar, das gründe danach. Die Ausgabe der Koordinaten bleibt allerdings die Selbe.

EDIT: Achso, Sinn und Zweck der Sache ist übrigens eine simple Kollisionserfrage mit intersects() zu ermögliche. Wenn jemand eine andere Methode zur Kollisionserkennung kennt, die nicht auf die Koordinaten angewiesen ist, ist das auch eine Hilfe nehme ich an.

Java:
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.pack();
        f.setVisible(true);
    }
}

class MyPanel extends JPanel {

    public MyPanel() {
        setBorder(BorderFactory.createLineBorder(Color.black));
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(800, 600);
    }

    @Override
    public void paintComponent(Graphics g) {
        //Upcast --> mehr Funktionen in Graphics2D
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        //neue Transformation erstellen
        AffineTransform tx = new AffineTransform();
        //ein Testrechteck:
        Rectangle2D.Double r = new Rectangle2D.Double(50, 50, 200, 200);
        System.out.println("Rechteck rot: " + r);

        //r vor Transformation:
        g2d.setColor(Color.red);
        g2d.fill(r);

        //Transformationen konkatenieren
        tx.rotate(60 * Math.PI / 180.0, r.getCenterX(), r.getCenterY());
        tx.translate(100, 0);

        //Transformation anwenden
        g2d.transform(tx);

        //r nach Transformation:
        g2d.setColor(new Color(0, 180, 0, 200));
        g2d.fill(r);

        System.out.println("Rechteck grün: " + r);
    }
}
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Ja, wenn man die AffineTransform von einem Graphics2D setzt, wird das Objekt nur gedreht gezeichnet - es IST aber nicht gedreht. Es gibt da mehrere mögliche Ansätze. Das erste "Problem" ist, dass das objekt ja als "Rechtangle" vorliegt. Das kann erstmal nicht (so wie man sich das vorstellt) gedreht sein, weil es ja nur eine Position und Größe hat, aber nichts, was eine Drehung repräsentieren könnte. Man könnte statt des Rectangles einen Path2D verwenden. DER kann mit einer AffineTransform gedreht werden, so dass sich auch die Eckpunkte verändern. Aber da ist der Überschneidungstest ggf. aufwändiger, muss man sich überlegen. Eine Alternative wäre, dass man vor dem Überschneidungstest das eine Objekt in den Raum des anderen Objektes transformiert: Wenn man zwei Objekte hat, X0 und X1, und die mit den Transformationen T0 und T1 transformiert, dann überschneiden die sich genau dann, wenn das UNtransformierte Objekt X0 mit (T0^-1)*X1 überschneidet. Hui. Das ist bestimmt falsch, nach 4 Stunden Schlaf und ohne Koffein. Aber so von der Grundidee her...
 

Quaxli

Top Contributor
AffineTransform wirkt sich nur auf die Zeichenebene ab, wie Du schon gemerkt hast.
Wenn Du Deine Objekte mitrotieren willst, wird es aufwändiger. Wäre es u. U. eine Option mit vorgefertigten Bildern zu arbeiten und sich auf einige Zwischenbilder zu beschränken?
Oder ist es wichtig, daß Dein Objekt die Bewegungsrichtung um wenige Grad ändern kann?
 

TheChemist

Bekanntes Mitglied
@Quaxli
Also da die Objekte sich flüssig um den Mittelpunkt rotieren lassen sollen, ist es schon wichtig, dass auch eine Rotation um wenige Grad möglich ist. Immoment wollte ich auch erstmal bei einer einfachen Repräsentation durch 2D-Objekte bleiben.

@Marco13
Der Ansatz mit dem Path klingt eigentlich ganz interessant, ich muss sagen deine anderen Vorschlag konnte ich nicht ganz nachvollziehen^^ (ist mit T0^-1 die umkehrende Transformation gemeint?) Den Path2D werde ich mir mal anschauen und kucken ob ich es damit schaffe eine Kollisionsabfrage zu basteln.

Erstma danke an euch Zwei, vllt. hat ja jemand noch einen anderen Tipp.
 

Marco13

Top Contributor
Das Problem beim Path ist, wie gesagt, dass die Überschneidungstests nicht mehr so einfach sind. (Schon einfach zu Programmieren, mit Area und Schnittmengenberechnung, aber das wäre wohl ein Overkill). Das gilt aber für alle geometrischen Formen. Nur bei Rechtecken kommt man mit den paar Vergleichen aus, die in rectangle.intersects(otherRectangle) eben so gemacht werden.

Mit T0^-1 ist die Inverse Transformation gemeint - kann man wohl "umkehrend" nennen. Also, ganz grob müßte das schon so stimmen, wenn's nicht hinhaut kann ich später nochmal schauen.
 

TheChemist

Bekanntes Mitglied
@Marco13

Noch ne Frage: Wie habe ich hier "(T0^-1)*X1" das "*" interpretieren? Ich nehme an das Ergebnis davon ist wieder ein Rectangle? Wäre zumindest logisch, dann kann ich wieder einfach prüfen ob sie x0 und x1 überschneiden.

EDIT: Hab mein Modell mal bisschen angepasst, die checkIntersect()-Methode funktioniert allerdings nicht, macht auch nicht so arg viel Sinn was da steht, da muss ich nochmal drüber schauen...

[Java]
import java.awt.geom.NoninvertibleTransformException;
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

public class Main {

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

public void run() {
createAndShowGUI();
}
});
}

private static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}

class MyPanel extends JPanel {

MyGameObject r1;
MyGameObject r2;

public MyPanel() {
r1 = new MyGameObject(50, 50, 150, 150, Color.red);
r2 = new MyGameObject(550, 50, 100, 100, Color.blue);
AffineTransform tx1 = new AffineTransform();
tx1.translate(250, 0);
r1.setTx(tx1);
AffineTransform tx2 = new AffineTransform();
tx2.translate(-250, 0);
r2.setTx(tx2);
}

@Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}

@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
r1.drawObject(g2d);
r2.drawObject(g2d);
g2d.drawString(checkIntersect(r1, r2) + "", 400, 300);
}

public boolean checkIntersect(MyGameObject go1, MyGameObject go2) {
AffineTransform t0 = go1.getTx();
AffineTransform t1 = go2.getTx();
try {
go2.setTx(t0.createInverse());
} catch (NoninvertibleTransformException ex) {
}
return go1.intersects(go2);
}
}

class MyGameObject extends Rectangle2D.Double {

AffineTransform tx;
Color color;

public MyGameObject(double x, double y, double width, double height,
Color color) {
super(x, y, width, height);
this.color = color;
}

public void drawObject(Graphics2D g) {
//Upcast --> mehr Funktionen in Graphics2D
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);

// vor Transformation:
g.setColor(color);
g.fill(this);
// nach Transformation
g.setTransform(tx);
g.fill(this);
g.setTransform(new AffineTransform());
}

public AffineTransform getTx() {
return tx;
}

public void setTx(AffineTransform tx) {
this.tx = tx;
}
}
[/Java]
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Nyee... sorry ...das funktioniert natürlich nicht wenn man nachher wieder Rectangles für den Überschneidugstest braucht *kopfpatsch* :oops:

Für beliebig gedrehte Rechtecke kann das etwas komplizierter werden, das ist dann z.B. hier 2D Rotated Rectangle Collision ganz gut beschrieben. Falls es nicht klappt... sowas kann man immer mal brauchen, vielleicht bastel' ich da morgen abend mal was.
 

TheChemist

Bekanntes Mitglied
Okay, der Link sieht echt gut aus. Ich nehme andie beliebig gedrehten Rechtecke realisiere ich schon wie vorher angesprochen mit dem Path2D? Dann werde ich in die Richtung mal weiter schauen.
 

Marco13

Top Contributor
Da gibt's dann mehrere Möglichkeiten, welche davon die "beste" ist, ist so im voraus schwer zu sagen. Aber eigentlich braucht man die "gedrehte geometrische repräsentation" vielleicht gar nicht. Eigentlich muss man ja nur die Vektoren transformieren, die man für die Berechnung der separating axes verwendet... Aber das muss man sich mal genauer ansehen.
 

TheChemist

Bekanntes Mitglied
Also nach ein bisschen mehr rumlesen habe ich rausgefunden, dass eine Area eigentlich das ist was ich suche, zumindest scheint es damit zu gehen, kann allerdings sein dass sich damit später Probleme auftun, aber naja.
Ich hab also meine Demoklasse bisschen umgeschrieben und habe dabei ein anderes Problem festgestellt. Warum überlagern sich die Shapes beim Bewegen? Vllt. kann ja jemand mal schnell das Beispiel komplieren und es sich anschauen was ich meine, ist direkt so ausführbar.

[Java]
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;

public class Main {

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

public void run() {
createAndShowGUI();
}
});
}

private static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setVisible(true);
}
}

class MyPanel extends JPanel implements Runnable {

MyGameObject r1;
MyGameObject r2;

public MyPanel() {
r1 = new MyGameObject(50, 50, 150, 150, Color.red);
r2 = new MyGameObject(550, 50, 100, 100, Color.blue);
AffineTransform tx2 = new AffineTransform();
tx2.rotate(45.0 * Math.PI / 180, r2.area.getBounds2D().getCenterX(), r2.area.getBounds2D().getCenterY());
r2.setTx(tx2);

Thread t = new Thread(this);
t.start();
}

@Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}

@Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
r1.drawObject(g2d);
r2.drawObject(g2d);
g2d.drawString(checkIntersect(r1, r2) + "", 400, 300);
}

public boolean checkIntersect(MyGameObject go1, MyGameObject go2) {
Area a1 = go1.area;
Area a2 = go2.area;
Area a1Copy = (Area) a1.clone();
a1Copy.intersect(a2);
return !a1Copy.isEmpty();
}

public void run() {
while (true) {
r1.moveObject();
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}
}

class MyGameObject {

Path2D.Double representation;
Area area;
AffineTransform tx = new AffineTransform();
Color color;

public MyGameObject(double x, double y, double width, double height,
Color color) {
area = new Area(new Rectangle2D.Double(x, y, width, height));
this.color = color;
}

public void moveObject() {
area.transform(AffineTransform.getTranslateInstance(10, 0));
}

public void drawObject(Graphics2D g) {
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.draw(area);
}

public AffineTransform getTx() {
return tx;
}

public void setTx(AffineTransform tx) {
area.transform(tx);
}
}
[/Java]
 

Marco13

Top Contributor
Spätere Probleme kann man teilweise vermeiden, wenn man sich übed die Schnittstellen im klaren ist - und diese ggf. sogar als Interfaces anbietet. Aber ich gehe davon aus, dass das nur ein Test war, ob es grundsätzlich geht.

Meinst du mit "überlagern" das, was durch die Zeile
Code:
    public void paintComponent(Graphics g) {
        [b]super.paintComponent(g);[/b]
verhindert wird?
 

TheChemist

Bekanntes Mitglied
Ja, das wars, oh man das war wieder zu einfach^^
Ich werde jetzt erst einmal mit den Areas arbeiten denke ich und schauen wie weit ich damit komme. Ein Problem das ich jetzt allerdings schon sehe wird sich bei der Rotation um den Mittelpunkt ergeben, der sich ja nicht so ohne weiteres bestimmen lässt. Zwar kann ich ihn annähern über den Mittelpunkt der BoundBox, aber das könnte teilweise ziemlich ungenau werden.

Aber naja, erstmal weiter schauen, vllt. klappt es ja doch.
 

Marco13

Top Contributor
Hmja, wie angedeutet: Du solltest dir genau überlegen, wie "MyGameObject" denn in der richtigen Anwendung aussehen sollte. Eigentlich sollte man sowas dann auch über ein interface beschreiben. Aber eine geeignete Klassenstruktur für die Kollisionserkennung potentiell beliebiger Implementierungen ist auf jeden Fall schwierig - da braucht man dann meistens doch einen etwas konkreteren Typ. Das Zeichnen kann man ja gut wegkapseln, aber bei den Kollisionen hängt die Erkennung eben von beiden Typen ab (wenn du z.B. ein Kreisförmiges Objekt haben willst, dann wäre die Kollisionserkennung mit einem anderen Kreisförmigen Objekt trivial, und es bräuchte auch keinen Path2D - aber bei der Erkennung einer Kollision Rechteck-Kreis muss man schon wissen, womit man es zu tun hat...)
 

TheChemist

Bekanntes Mitglied
Ja du hast recht. Ich werde mich allerdings erstmal damit zufrieden geben nur Rechtecke durch die Areas zu beschrieben. Sollte das irgendwann mal alles so funktionieren wie ich es mir vorstelle, werde ich vllt. versuchen noch andere Formen darzustellen. Ich werde erste Ergenisse hier vllt. mal hochladen wenn ich in nächster Zeit welche zu Stande bringe...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
E Scaling Probleme Spiele- und Multimedia-Programmierung 6
J Probleme bei Pong Spiele- und Multimedia-Programmierung 9
D Java Bomberman Probleme java.lang.NullPointerException Spiele- und Multimedia-Programmierung 1
J YoutubeAPI Livestream probleme Spiele- und Multimedia-Programmierung 3
G [LibGDX] Button Klick Probleme Spiele- und Multimedia-Programmierung 1
T Probleme mit JButton Spiele- und Multimedia-Programmierung 5
T Probleme bei "Pixel-Fighting"-Spiel: Unausgewogene Mannschaften??? Spiele- und Multimedia-Programmierung 4
P Probleme mit VLCJ Spiele- und Multimedia-Programmierung 0
F Probleme bei der Soundwiedergabe Spiele- und Multimedia-Programmierung 0
S Probleme bei Breakout - Brick kollision Spiele- und Multimedia-Programmierung 2
S 2D-Render Probleme LWJGL 2 (Java) Spiele- und Multimedia-Programmierung 1
F BlueJ Ufospiel Probleme Spiele- und Multimedia-Programmierung 1
B Probleme mit AndEngine in Android Spiele- und Multimedia-Programmierung 1
M 2048, 3 kleine Probleme Spiele- und Multimedia-Programmierung 4
A Probleme mit Darstellung von Umgebungen mittels mehrdimensionaler Arrays Spiele- und Multimedia-Programmierung 8
J Java Game performance Probleme Spiele- und Multimedia-Programmierung 7
J Perfomance Probleme beim eigenen Editor Spiele- und Multimedia-Programmierung 1
K Probleme beim kompilieren von javakara Spiele- und Multimedia-Programmierung 10
Q LWJGL - Alpha-Probleme Spiele- und Multimedia-Programmierung 2
M Point & Click Thread Probleme Spiele- und Multimedia-Programmierung 20
K Probleme mit .jar Spiele- und Multimedia-Programmierung 12
L Probleme beim kompilieren von javakara Spiele- und Multimedia-Programmierung 3
D Probleme mit der Runnable jar Datei Spiele- und Multimedia-Programmierung 3
D Probleme mit objekt initializirung mit Mouselistener Spiele- und Multimedia-Programmierung 10
Black_ixx Hintergrund & Koordinaten Probleme Spiele- und Multimedia-Programmierung 2
B Probleme mit Texturen Spiele- und Multimedia-Programmierung 7
Maxim6394 Probleme bei Sidescroller Spiele- und Multimedia-Programmierung 5
R Probleme mit JPanel!KeyListener geht nicht Spiele- und Multimedia-Programmierung 6
Maxim6394 [Java3D] Probleme bei Kollision Spiele- und Multimedia-Programmierung 7
Maxim6394 [Java3D] Probleme mit KeyFrame Animationen Spiele- und Multimedia-Programmierung 9
T Probleme mit Skysphere in Opengl Spiele- und Multimedia-Programmierung 4
B Probleme mit redraw() Spiele- und Multimedia-Programmierung 3
Gossi Quaxlis 2D Tutorial....Probleme nach hinzufügen der Kollisionsabfrage Spiele- und Multimedia-Programmierung 16
Gossi Probleme beim Laden der Images aus dem "Tutorial für Java-Spiele" Spiele- und Multimedia-Programmierung 4
S Probleme mit Tutorial Spiele- und Multimedia-Programmierung 3
W Probleme mit Mouselook Spiele- und Multimedia-Programmierung 2
B GameGrid Probleme mit mehrere Actors Spiele- und Multimedia-Programmierung 5
B GameGrid Probleme mit mehrere Actors Spiele- und Multimedia-Programmierung 2
M [Spiel] Kartenspiel Leben und Tod Tips und Probleme Spiele- und Multimedia-Programmierung 7
G [Java3D] Probleme bei Animation Spiele- und Multimedia-Programmierung 4
S Probleme mit JMenu in einem JFrame mit BufferStrategy Spiele- und Multimedia-Programmierung 2
Steev Probleme mit Kameraausrichtung bei ISO-Map Spiele- und Multimedia-Programmierung 3
R MediaPlayer macht Probleme Spiele- und Multimedia-Programmierung 2
N Jogl Probleme mit dem Buffer beim laden einer Textur Spiele- und Multimedia-Programmierung 2
prakdi Probleme mit Quaxlis tutorial Spiele- und Multimedia-Programmierung 5
D Java Pong Probleme Spiele- und Multimedia-Programmierung 7
T Java Sound Probleme Spiele- und Multimedia-Programmierung 8
P probleme mit key event Spiele- und Multimedia-Programmierung 11
T Bekanntes Heli Spiel -> Aber Probleme damit Spiele- und Multimedia-Programmierung 30
S Probleme mit Thread beim Streaming Spiele- und Multimedia-Programmierung 1
O Ampel - Probleme mit der Farbgebung Spiele- und Multimedia-Programmierung 16
F Probleme bei Bewegung Spiele- und Multimedia-Programmierung 7
P Probleme mit Vista und JOGL Spiele- und Multimedia-Programmierung 2
P Probleme mit Wolkenbewegung Spiele- und Multimedia-Programmierung 5
W Probleme mit dem setTextureCoordinate Spiele- und Multimedia-Programmierung 3
D Probleme beim Download von GIF-Bildern Spiele- und Multimedia-Programmierung 4
S Probleme mit dem Licht und dem KeyListener Spiele- und Multimedia-Programmierung 2
L Probleme Bei Pong Programmierung Spiele- und Multimedia-Programmierung 2
D Probleme bei ATI Karten bekannt? Spiele- und Multimedia-Programmierung 4
H Probleme bei Rotation Spiele- und Multimedia-Programmierung 9
X Probleme. Spiele- und Multimedia-Programmierung 2
E Probleme mit Kollisionserkennung ! Spiele- und Multimedia-Programmierung 2
F Probleme mit selbsterstelltem transparenten PNG Spiele- und Multimedia-Programmierung 5
S probleme mit material Spiele- und Multimedia-Programmierung 2
W Probleme beim entfernen von Childs im HauptSceneGraph Spiele- und Multimedia-Programmierung 8
N Pong - noch 2 kleinere Probleme Spiele- und Multimedia-Programmierung 16
M Probleme mit WaveFront-Object - Datei Spiele- und Multimedia-Programmierung 7
B Probleme beim zeichnen Spiele- und Multimedia-Programmierung 15
D Gomoku --- Probleme bei Instanzierung Spiele- und Multimedia-Programmierung 2
G Probleme beim installieren java 3d linux Spiele- und Multimedia-Programmierung 4
G Sound Probleme Spiele- und Multimedia-Programmierung 2
S Probleme mit Canvas! Spiele- und Multimedia-Programmierung 2
S Jump'n'Run: Probleme mit Kollision Spiele- und Multimedia-Programmierung 13
C Probleme mit Java3D (sun.awt.DrawingSurface) in Java 5 Spiele- und Multimedia-Programmierung 10
R Probleme mit Sound in Applikation. HILFE Spiele- und Multimedia-Programmierung 5
N Probleme mit View Spiele- und Multimedia-Programmierung 3
E relevanter bereich einer isometrischen karte zeichnen (AffineTransform) Spiele- und Multimedia-Programmierung 0
A AffineTransform: Nach Drehen verschieben Spiele- und Multimedia-Programmierung 2
M Skalieren mit AffineTransform und SCALE_SMOOTH? Spiele- und Multimedia-Programmierung 3
M Bildrauschen bei AffineTransform? Spiele- und Multimedia-Programmierung 2
G AffineTransform macht programm immer langsamer Spiele- und Multimedia-Programmierung 3
H Verständnisproblem GeneralPath/AffineTransform Spiele- und Multimedia-Programmierung 2
K AffineTransform Spiele- und Multimedia-Programmierung 2

Ähnliche Java Themen

Neue Themen


Oben