Affine Transforms and rotating images

I was wondering how to rotate a png image. I have tried searching the forums for relevant information, but haven’t been able to figure out the problem yet. Some of the topics I’ve read about using Affine Transform to rotate my images don’t make a whole lot of sense to me.
How am I supposed to use Affine Transform to rotate my sprite? I’ve already tried doing something akin to this:

[quote]Here is one method I use:

Write a draw(Graphics2D) method for the Sprite class.

In the painting method, you can store the current AffineTransfrom of the Graphics2D with

Code:

AffineTransform emptyXform = g2d.getTransform();
for( all the sprites ){
g2d.setTransform(emptyXform);
sprite.draw(g2d)
}

In the draw method of the sprite you can do any transformation necessary on the Graphics2D without wrecking anything. emptyXform simply resets the transform to one which doesn’t do anything (it’s probably just the identity transformation). Simply use

Code:
g2d.rotate(angle, centerX, centerY);

inside the draw() methods of the sprites.
[/quote]
(posted by Ask_Hjorth_Larsen, May 16, 2005)

However, what this ends up doing is rotating everything on the screen, including my sprite, and background image.

Thanks for any help!

since the Graphics is drawing the entire screen, the AffineTransform is also affecting the entire screen. This means when you set up an anchor point for rotation, you need to set it relative to its X and Y positions on the screen. Also, whenever you do ANY individual transform (for a single sprite or whatever), you should ALWAYS reset Graphics’s transform to the original transform. Like so:


AffineTransform orig = g2d.getTransform();
g2d.setTransform(...);
// do rotated drawing here
g2d.setTransform(orig);
// continue with normal drawing
// (or loop back to doing another rotated drawing)

Now I’ll elaborate more about the “anchor point” I mentioned earler. This is were the center of the “rotation circle” would be. So if you wanted to rotate an image from the image’s center (similiar to how a tire or CD spins… from the center), you need to set the anchor point to:


new Point(imageX+(imageWidth/2),imageY+(imageHeight/2);

if you were to set the anchor point to just the imageX and imageY values (without adding anything else), the image would be rotated from its top-left corner… kinda as if it was being dragged :wink:

I coded an example for you to (hopefully) clear things up.

RotationTest.jar | Source

Hope this helps :smiley:

Ok, nice. Thanks man - it works well now.

Just one question though: I don’t quite understand how only the sprite is rotated, and not everything else along with it. I know that setting the transform of the Graphics2D object used to draw everything to the screen to an empty transform does something, but I’m not quite sure what.

Everything you draw with a Graphics2D will be transformed by the Graphics2D’s transform. Thus, as you know, if you just call g2d.rotate(something), it will permanently alter the transform. This is why the original transform is backed up in the beginning. Then each sprite can, during its draw method, arbitrarily transform the Graphics2D object. This will NOT alter the backup transform, since the Graphics2D stores its transform elsewhere. When a sprite is finished drawing, resetting the transform to the backup one will simply make the Graphics2D forget any changes which the last sprite might have made to its transform.

You can also do this:


Graphics2D newG = g2d.create(); // creates a copy of g2d
newG.setTransform()...
newG.drawImage()..
// do whatever with newG
newG.dispose();

// no need to restore g2d's attributes

Can you give some idea of where the line is in terms of it being faster to create a new graphics context vs. save and restore value in a single context? E.g. if it is just a single transform, I’m guessing it may not be worth it. But if you have to save and restore the transform, and the current color, and line stroke, etc… then it probably makes more sense to just create a temporary context.

Am I correct?