Reputation: 1261
Perhaps a question with a simple answer. I'm trying to animate a ship (asteroids style). Right now I'm just using the Graphics2D rotate method. However, right now it's just blurring my image. What's the simplest way of going about this and getting it to work correctly? (the getImage method gets called every time the screen refreshes, and the rotate method gets called every time the user presses left or right. bi1 is the bufferedimage read in previously)
public void rotate(double rot) {
g = bi1.getGraphics();
Graphics2D g2d=(Graphics2D)g;
g2d.rotate(rot, 15, 15);
g2d.drawImage(bi1, 0, 0, null);
}
public BufferedImage getImage() {
return bi1;
}
Upvotes: 3
Views: 3158
Reputation: 3712
try it using an affine transformation:
public void paint(Graphics g) {
// clear off screen bitmap
super.paint(g);
// cast graphics to graphics 2D
Graphics2D g2 = (Graphics2D) g;
AffineTransform tfm = new AffineTransform();
tfm.rotate(0,0,0);
g2.setTransform(tfm);
g2.drawImage(backImage, 0, 0, this);
tfm.rotate(Math.toRadians(player.angle+90), player.x+32, player.y+32);
g2.setTransform(tfm);
g2.drawImage(tank, player.x, player.y, this);
}
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/geom/AffineTransform.html
Upvotes: 2
Reputation: 3440
you can use getRotateInstance(double theta)
public void paint(Graphics g) {
...
Graphics2D g2d = (Graphics2D)bi1.getGraphics();
AffineTransform af = new AffineTransform(
AffineTransform.getRotateInstance(theta, x, y));
g2d.setTransform(af);
g2d.drawImage(bi1, af, this);
}
docs: AffineTransform (getRotateInstance)
Upvotes: 0
Reputation: 4523
You are drawing to the graphics context of the BufferedImage that is storing your ship image.
Your use of the rotate method should work if you draw to the graphics context of the UI component that is displaying the game or the context of some other buffer.
Upvotes: 0
Reputation: 46960
I agree with the suggestion on Graphics2D.setRenderingHint()
. Try KEY_INTERPOLATION
with VALUE_INTERPOLATION_BILINEAR
.
Additionally, try making the source image up to 4 times bigger than you actually want to draw it and then use Graphics2D.scale(1/multiple)
in addition to the rotation.
The reason: Without scaling, the diagonal of a pixel is 1.4+ times as large as an edge, so as the rotation approaches the odd 45 degree multiples, 14+ pixels in the image are being drawn with reference to only 10 in the original image. This adds raggedness to the result.
Another approach is to use BufferedImage
for both source and destination:
tx = new AffineTransform();
tx.rotate(theta, xCenter, yCenter)
op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
BufferedImage destImg = op.filter(srcImg, null);
Finally, switching to OpenGL
(e.g. with JOGL or LWGL), provides all kinds of control over anti-aliasing and much more. On the other hand, it opens a door for hardware incompatibilities as many graphics drivers have OpenGL
bugs IME.
Upvotes: 1
Reputation: 20059
You can try playing with Graphics.setRenderingHint() and set a higher quality, but other than that there isn't anything you can do to make it work 'right'.
If the quality provided by Graphics2D does not satisfy your demands, create rotated images of your 'spaceship' with a graphics program and select the correct pre-rotated image depending on the facing of the ship. This way the quality depends no longer on the graphics API, but only on your graphics program (and how much effort you put into making the rotated images). You have to decide on a granularity (number of prerendered images) for the angle, sane numbers are usually between 16 to 64.
Upvotes: 2