# Rundenstrategiespiel - Problem beim Drehen eines Bildes



## Neolity (25. Sep 2006)

Hallo,

ich beschäftige mich zur Zeit ein wenig mit einem kleinen Rundenstrategiespiel.
Dabei bin ich im Augenblick so weit, dass eine Einheit (ein .png Bild) über ein schachbrettartiges Spielfeld gesteuert wird.
(gesteuert wird über mehrere Buttons, die Pfeilbilder als ImageIcons haben, damit man die Richtung erkennen kann)
Nun wollte ich es so machen, dass die Einheit nicht nur in eine Richtung schaut, sondern sich immer passend zur "Fahrtrichtung" dreht. Mein erster Gedanke war einfach 8 Bilder der Einheit für alle Richtungen zu erstellen. Das würde mir aber bei mehreren Einheiten etwas zu aufwendig. Daher mein Gedanke das Bild einfach zu drehen.
Der Code Abschnitt dafür sieht im Augenblick so aus:

```
eins.img = getToolkit().getImage("images/Einheiten/Panzer/Panzer.png");
  		Graphics2D g2d = (Graphics2D) g;
  		AffineTransform aft = new AffineTransform();
  		aft.rotate(Math.toRadians(90));
		g2d.drawImage(eins.img, aft, null);
```
(eins ist die Instanz meiner "Einheit" Klasse)
Das Problem ist, dass ich vorher bei drawImage die Koordinaten für die Position der Einheit angegeben habe.
Die Frage ist nun, wie ich das jetzt machen soll, sprich gleichzeitig rotieren und Positionsangabe?

Vielen Dank!


----------



## w00t (25. Sep 2006)

Normalerweise kann man ein 2D bild nicht drehen. Du kannst es natürlich vertikal und horizontal drehen, aber so wie ich das verstanden habe brauchst du ein Bild, sagen wir von einem Pferd, von vorne, hinten, links, rechts, und die anderen 4 richtungen. Das geht nicht mit einem Bild, da in einem normalen Bild diese Informationen nicht verfügbar sind, wegen: 2D, nicht 3D


----------



## LoN_Nemesis (25. Sep 2006)

Wenn es ein schachbrettartiges Spielfeld ist, dann denke ich mal dass man es aus einer Art Vogelperspektive betrachtet. Wenn das so ist, dann macht Rotieren durchaus Sinn, allerdings sehe ich das Problem irgendwie nicht. Die Position deiner Einheit verändert sich doch nicht, wenn du das Bild drehst.

Vielleicht kannst du nochmal einen Screenshot oder Code zeigen, auf dem dein Problem deutlich wird.

EDIT: Ach jetzt verstehe ich dein Problem. Du malst dein Bild oben im Code mit

```
g2d.drawImage(eins.img, aft, null);
```
Und da gibst du nur die Transformation an, aber keine Koordinaten mehr.

Die Lösung dafür ist folgendes. Du musst das Bild 2mal malen. Einmal temporär in ein Zwischenimage, dort drehst du dann. Und dann zeichnest du dieses gedrehte Bild wieder auf den Bildschirm.

Wenn du magst, kannst du auch einfach die Klasse benutzen, die ich am Ende des Threads 2D Projektil Flugbahn gepostet habe. Die macht das alles für dich.


----------



## Neolity (25. Sep 2006)

hmm, ich hab mir mal deine Klasse angeschaut! 
Aber ich werde da im Grunde gar nicht schlau draus! 
Ich habe bisher das hier zusammengecodet:


> eins.img = getToolkit().getImage("images/Einheiten/Panzer/Panzer.png");
> BufferedImage temp_neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
> BufferedImage neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
> Graphics2D g2d = (Graphics2D) g;
> ...


Einziges Proglem dabei: Es funktioniert nicht!
Zum einen bekomme ich eine Fehlermeldung, dass er "getRotateInstance" nicht kennt und zum anderen tut sich auf dem Bildschirm einfach gar nichts. Da wird kein einziges Bild ausgegeben!


----------



## LoN_Nemesis (25. Sep 2006)

Ich hatte das Problem auch am Anfang, eigentlich sollte es so gehen aber tut es nicht. Versuch mal statt getToolkit().getImage("images/Einheiten/Panzer/Panzer.png");  das Bild mit der ImageIO zu laden, dann bekommst du gleich ein BufferedImage 
	
	
	
	





```
ImageIO.read("images/Einheiten/Panzer/Panzer.png");
```
 . Eigentlich sollte es auch gehen, wenn du erst das normale Image in ein BufferedImage reinmalst, aber das funktionierte bei mir auch nicht.

Edit: es kann sein, dass es .getRotateInstance erst ab Java 1.5 gibt


----------



## Neolity (25. Sep 2006)

hmm, ich hab es jetzt so gemacht:

```
try
		{
			eins.img =  ImageIO.read("images/Einheiten/Panzer/Panzer.png");
		}
		catch (IOException e)
		{

		}
		BufferedImage temp_neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
		BufferedImage neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
  		Graphics2D g2d = (Graphics2D) g;
  		AffineTransform aft = new AffineTransform.getRotateInstance(Math.toRadians(90), 25, 25);
  		Graphics2D g1 = temp_neues_bild.createGraphics();
  		g1.drawImage(eins.img, 25, 25, null);
  		Graphics2D g2 = neues_bild.createGraphics();
		g2.setTransform(aft);
		g2d.drawImage(neues_bild, eins.x, eins.y, this);
```
Er findet aber angeblich die Methode read nicht.
Dabei hab ich folgendes eingebunden:

```
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.geom.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.IOException;
```


----------



## LoN_Nemesis (26. Sep 2006)

Sorry mein Fehler, der read Methode muss man entweder ein File, einen InputStream oder eine URL übergeben, einfach nur ein String geht nicht.

P.S.: Hast du eigentlich Java 1.5? Wenn nicht lohnt es sich vielleicht upzudaten.


----------



## Neolity (27. Sep 2006)

Aber mein Bild ist doch ein File?!
Wie bekomme ich das Bild denn in ein File bzw. einen InputReader bzw. ganz platt gefragt, was muss ich tun?


----------



## LoN_Nemesis (27. Sep 2006)

Du schreibst einfach:


```
eins.img =  ImageIO.read(new URL("images/Einheiten/Panzer/Panzer.png"));
```


----------



## Neolity (27. Sep 2006)

Vielen Dank schon mal! 

Es sieht jetzt so aus:

```
try
		{
			eins.img =  ImageIO.read(new URL("images/Einheiten/Panzer/Panzer.png"));
		}
		catch (IOException e)
		{

		}
		BufferedImage temp_neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
		BufferedImage neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
  		Graphics2D g2d = (Graphics2D) g;
  		AffineTransform aft = new AffineTransform.getRotateInstance(Math.toRadians(90), 25, 25);
  		Graphics2D g1 = temp_neues_bild.createGraphics();
  		g1.drawImage(eins.img, 25, 25, null);
  		Graphics2D g2 = neues_bild.createGraphics();
		g2.setTransform(aft);
		g2d.drawImage(neues_bild, eins.x, eins.y, this);
```

Aber es funktioniert immer noch nicht. Ich hab immer noch den Fehler, dass er getRotateInstance nicht findet...


----------



## LoN_Nemesis (27. Sep 2006)

Das macht nichts, du kannst das ersetzen durch:


```
AffineTransform aft = new AffineTransform();
        aft.rotate(Math.toRadians(90), 25, 25);
```

Sollte völlig identisch sein.


----------



## Neolity (28. Sep 2006)

Danke! Der Fehler ist jetzt weg, aber auf dem Bildschirm wird trotzdem nix ausgegeben!


----------



## LoN_Nemesis (28. Sep 2006)

Probier mal nur eins.img zu zeichnen, nachdem du es mit ImageIO eingelesen hast, also ohne irgendwelche Transformationen, klappt das denn?


----------



## Neolity (28. Sep 2006)

Nein, das alleine funzt schon ned!

Der Code Abschnitt sieht so aus:

```
try
		{
			eins.img =  ImageIO.read(new URL("images/Einheiten/Panzer/Panzer.png"));
		}
		catch (IOException e)
		{
```


----------



## LoN_Nemesis (28. Sep 2006)

Versuch mal folgendes:



```
eins.img =  ImageIO.read(new File("./images/Einheiten/Panzer/Panzer.png"));
```

natürlich auch wieder im try/catch Block


----------



## Neolity (28. Sep 2006)

hmm, ohne irgendwas zu drehen funktioniert das mit dem File laden. Wenn ich aber rotiere, dann wird gar kein Bild mehr angezeigt... 

Sieht jetzt insgesamt so aus:


```
try
		{
			eins.img =  ImageIO.read(new File("images/Einheiten/Panzer/Panzer.png"));
		}
		catch (IOException e)
		{

		}
		BufferedImage temp_neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
		BufferedImage neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
  		Graphics2D g2d = (Graphics2D) g;
  		AffineTransform aft = new AffineTransform();
  		aft.rotate(Math.toRadians(90), 25, 25);
  		Graphics2D g1 = temp_neues_bild.createGraphics();
  		g1.drawImage(eins.img, 25, 25, null);
  		Graphics2D g2 = neues_bild.createGraphics();
		g2.setTransform(aft);
		g2d.drawImage(neues_bild, eins.x, eins.y, this);
```


----------



## LoN_Nemesis (28. Sep 2006)

Versuchs mal damit:


```
try
		{
			eins.img =  ImageIO.read(new File("images/Einheiten/Panzer/Panzer.png"));
		}
		catch (IOException e)
		{

		}
		BufferedImage temp_neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
		BufferedImage neues_bild = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
  		Graphics2D g2d = (Graphics2D) g;
  		AffineTransform aft = new AffineTransform();
  		aft.rotate(Math.toRadians(90), 25, 25);
  		Graphics2D g1 = temp_neues_bild.createGraphics();
  		g1.drawImage(eins.img, 0, 0, null);
  		Graphics2D g2 = neues_bild.createGraphics();
		g2.setTransform(aft);
		g2.drawImage(temp_neues_bild, 0, 0, null);
		g2d.drawImage(neues_bild, eins.x, eins.y, this);
```

Btw: die 2 neuen BufferedImages brauchst du nur, wenn du nicht um vielfache von 90° drehst, denn dann hat dein Endbild eine andere Grösse als das Ausgangsbild.


----------



## Neolity (29. Sep 2006)

Wenn ich diese Zeile noch einfüge:

```
g2.drawImage(temp_neues_bild, 0, 0, null);
```
dann erscheint ein kleiner Teil des Bildes auf dem Bildschirm. Ändere ich die beiden nullen aber in eins.x oder eins.y oder irgendwelche Zahlenwerte ab, dann passiert nichts!  ???:L


----------



## LoN_Nemesis (29. Sep 2006)

Ja das ist genau das Problem mit dem Rotieren, deswegen habe ich mir die genannte Klasse geschrieben. Die berechnet diese Verschiebungen und zeigt das Bild (so gut wie) immer richtig an.


```
g2.drawImage(temp_neues_bild, 0, 0, null);
```

Diese Nullen darf du nicht in eins.x, eins.y ändern. Hier malst du nur das Bild gedreht in ein Zwischenbild.


```
g1.drawImage(eins.img, 25, 25, null);
```

Hier sollten auch 0, 0 stehen meiner Meinung nach statt 25,25. Zumindest wenn du nur in 90° Winkeln drehst.


```
g2d.drawImage(neues_bild, eins.x, eins.y, this);
```

Erst hier malst du das eigentlich sichtbare Bild, deswegen muss hier eins.x, eins.y stehen.

Wenn du magst kannst du auch einfach meine Klasse komplett kopieren und bei dir benutzen. Ich glaube du willst ja im Endeffekt für jede Einheit 8 verschiedene Richtungen, wenn ich das richtig verstanden habe? Dann brauchst du auch 45° Winkel und da fangen die wirklichen Probleme erst an. Denn dann reicht es nicht dein BufferedImage so gross wie das Original zu machen, es muss größer sein.


----------

