# Rotation von Sprite klappt nicht



## Paladin (22. Jan 2013)

Liebe Community,

bisher habe ich eigentlich keine Erfahrung mit der Programmierung von Spielen. Ich habe mir vorgenommen mal ein kleines Spiel in Java zu Programmieren um zu sehen wie gut oder schlecht Java dafür geeignet ist / bzw. wo ich konkret auf Probleme stoße.

Für die Entwicklung des Spiels verwende ich LWJGL und das funktioniert soweit ganz gut. Also Sprites darstellen, bewegen, Kollision usw. funktioniert problemlos. Derzeit scheitere ich daran, einen einfachen Sprite auf dem Bildschirm (rotiert) darzustellen. Ich versuche einen Tacho (wie aus dem Auto) auf dem Screen darzustellen. Dazu habe ich einen Sprite für das Tachoblatt (der wird nicht gedreht angezeigt) und einen Sprite für die Tachonadel. Die Schwierigkeit ist hier, dass der Drehpunkt der Tachonadel nicht die Mitte des Sprites ist (sondern am unteren mittleren Rand des Bildes).

Ich habe bei Google schon einen Haufen Information zu dem Problem gefunden und mir daraus einen Quelltext zusammengesetzt der teilweise funktioniert. Was mir aber nicht gelingt ist die korrekte Drehung der Tachonadel um den Ursprung (der ja nicht in der Mitte des Bildes sonder am unteren mittleren Rand des Bildes ist). Der Effekt ist, dass der Sprite "umherwandert".

Hier mein aktueller Code zur Anzeige des Sprites:

1) Diese Funktion erzeugt eine rotierte Variante des Originalbildes


```
public BufferedImage getRotatedImage(int angle) {
  //buf ist das Originalbild (Tachonadel)
  double width = buf.getWidth();
  double height = buf.getHeight();
  double sin = Math.abs(Math.sin(Math.toRadians(angle)));
  double cos = Math.abs(Math.cos(Math.toRadians(angle)));

  //Berechne Größe für neues Bild
  int neww = (int)Math.round(((width)*cos)+(height*sin));
  int newh = (int)Math.round((height*cos)+((width)*sin));
  BufferedImage dimg = new BufferedImage(neww, newh, buf.getType());
  Graphics2D g = dimg.createGraphics();
  g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
  g.translate((neww-width)/2, (newh-height)/2);
  g.rotate(Math.toRadians(angle), width/2, newh/2);
  g.drawRenderedImage(buf, null);
  return dimg;
}
```

2) Diese Funktion erzeugt eine Textur aus dem rotierten Bild


```
public int getRotatedTexture(int angle) {
  tmpBuf = getRotatedImage(angle);
  try {
    this.setTmpTex(BufferedImageUtil.getTexture("", tmpBuf));
  } catch (IOException e) {
  // TODO Auto-generated catch block
    e.printStackTrace();
  }

  int[] pixels = new int[tmpBuf.getWidth() * tmpBuf.getHeight()];
  tmpBuf.getRGB(0, 0, tmpBuf.getWidth(), tmpBuf.getHeight(), pixels, 0, tmpBuf.getWidth());
  byteBuffer = BufferUtils.createByteBuffer(tmpBuf.getWidth() * tmpBuf.getHeight() *  
  BYTES_PER_PIXEL);
  for(int y = 0; y < tmpBuf.getHeight(); y++) {
    for(int x = 0; x < tmpBuf.getWidth(); x++) {
      int pixel = pixels[y * tmpBuf.getWidth() + x];
      byteBuffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
      byteBuffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
      byteBuffer.put((byte) (pixel & 0xFF));               // Blue component
      byteBuffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
    }
  }
		
  byteBuffer.flip();
	
  textureID = GL11.glGenTextures();
  GL11.glEnable(GL11.GL_TEXTURE_2D);
  GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
  GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
  GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
  GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, tmpBuf.getWidth(),   tmpBuf.getHeight(), 0, GL11.GL_RGBA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, byteBuffer);
  return textureID;
}
```

3) Diese Funktion zeigt das Bild auf dem Screen an


```
public void drawPolygon1(int id, int x, int y, int rotation) {
  GL11.glPushMatrix();
  GL11.glTranslatef(x, y, 0);

  //Erzeuge eine Textur(rotiert) von dem gewünschten Sprite
  settings.getSprite(id).getSpritePolygon().getRotatedTexture(rotation);
  tmpTex = settings.getSprite(id).getSpritePolygon().getTmpTex();
	
  GL11.glBegin(GL11.GL_QUADS);
  {
    GL11.glTexCoord2f(0,0);
    GL11.glVertex2f(0,0);
    GL11.glTexCoord2f(1,0);
    GL11.glVertex2f(tmpTex.getImageWidth(),0);
    GL11.glTexCoord2f(1,1);
    GL11.glVertex2f(tmpTex.getImageWidth(),tmpTex.getImageHeight());
    GL11.glTexCoord2f(0,1);
    GL11.glVertex2f(0,tmpTex.getImageHeight());
  }
  GL11.glEnd();
  GL11.glPopMatrix();
}
```

Ich sitze an diesem Problem jetzt schon einige Tage und komme einfach nicht auf die Lösung. Sicherlich sind meine mangelnden Kenntnisse in Mathematik auch nicht gerade förderlich aber vielleicht könnt Ihr mir ja einen Hinweis geben wie ich weiterkomme.

Viele Grüße

Paladin


----------



## Marco13 (22. Jan 2013)

Warum rotierst du die Textur manuell? Lass' das doch OpenGL machen!? (glRotatef mit dem Winkel)


----------



## Paladin (22. Jan 2013)

Ich habe folgendes versucht:

1) Erst den Ursprung zum Rotationspunkt verschieben.
GL11.glTranslatef((x+(tmpTex.getWidth()/2)), (y+(tmpTex.getHeight()-5)), 0);

2) Dann die Rotation
GL11.glRotatef((float)Float.valueOf(rotation),0.0f,0.0f,1.0f);

Das klappt zwar so (die Textur dreht sich) aber die Drehung erfolgt nicht über den von mir gewünschten Punkt. Konkret im Falle der Tachonadel: Der Drehpunkt der Grafik ist die Spitze der Tachonadel.


----------



## Marco13 (22. Jan 2013)

3. ... und wieder zurück - quasi so wie es in der Methode von AffineTransform (Java Platform SE 6) beschrieben ist, die auch interessant sein könnte, FALLS du das wirklich manuell rotieren wolltest - was aber vermutlich nicht der Fall ist (das könnte zwar auch davon abhängen, ob die Rotation nur einmal am Anfang gemacht wird, oder sie sich ständig ändert, aber in keinem Fall würde ich spontan einen konkreten Anlass sehen, ein rotiertes BufferedImage-Textur zu erstellen...)


----------



## Paladin (22. Jan 2013)

Ok, das klappt. Ich habe das zweite Translate vergessen (und nebenbei noch gelernt, dass man sich den manuellen Aufwand sparen kann).

Danke Marco

Paladin


----------

