0

So Im drawing a BufferedImage 'bird' but I want to rotate it according to the angle that it is falling. I have a bird object which contains the BufferedImage and a render() method which draw it rotated.

public void render(Graphics2D g, ImageObserver io) {

    double theta = Math.tan((height - pastHeight) / .875);
    System.out.println(theta);
    Graphics2D g2 = (Graphics2D) bird.getGraphics();

    g2.drawImage(bird, 100, (int) height, null);

    g2.rotate(theta);

    g2.drawImage(bird, 100, (int) height, io);
}

I call this as such

bird.render(g2, ???);

in my paintcomponent method in my jcomponent.

only problem is I dont know what to use as my ImageObserver... I've tried passing in my JFrame and my JComponent but the image no longer appears when I do that... what would I pass in for the image to appear in my window and/or how else would I achieve this rotation?

Acor74u
  • 17
  • 5

1 Answers1

1

Assuming that you are doing this in something that extends JComponent, you should use

bird.render(g2, this);

As JComponent implements ImageObserver

The problem with the image disappearing isn't an issue with the ImageObserver but the point around which the rotation is occurring, which I believe is the top/left corner of the Graphics context.

Try using Graphics2D#rotate(double, int, int) which will allow you to specify the origin points of the rotation (pivot point).

Don't forget to reset your translations, as they will effect everything that is painted after your supply them and may be re-used in subsequent paint cycles.

Updated with simple example

This is a basic example that demonstrates the different uses of rotate.

First, I simply used Graphics#rotate(double)

rotate

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RotateImage {

    public static void main(String[] args) {
        new RotateImage();
    }

    public RotateImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;
        private double angel = 0d;

        public TestPane() {
            try {
                img = ImageIO.read(...);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angel += 5;
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.rotate(Math.toRadians(angel));
                int x = (getWidth() - img.getWidth()) / 2;
                int y = (getHeight() - img.getHeight()) / 2;
                g2d.drawImage(img, x, y, this);
                g2d.dispose();
            }
        }
    }

}

Then I replaced g2d.rotate(Math.toRadians(angel)); with g2d.rotate(Math.toRadians(angel), getWidth() / 2, getHeight() / 2);, which used the center position of the component (or the Graphics context) as the anchor point around which the rotation would occur...

Center

Now, because you only want to rotate your image, you're going to need to calculate the anchor point around the current position of the image's center position (assuming you want it to rotate around the middle)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • thats the first thing I tried, the image isn't diplayed and no errors or exceptions are thrown – Acor74u Feb 17 '14 at 23:59
  • Did you try using `rotate(double, int, int)` instead? – MadProgrammer Feb 18 '14 at 00:00
  • hmm i could..would I just make the ints then? – Acor74u Feb 18 '14 at 00:15
  • The `x`/`y` points are the anchor point around which the rotation should occur, take a look at the included examples – MadProgrammer Feb 18 '14 at 00:16
  • aw ok ive done this with other images but since I'm drawing other things on the same graphics object (the ground, the sky, the level) I can't rotate the entire world. Im only having this problem when I have to rotate only one thing is the world (the bird) thats why I made a new graphics2d object – Acor74u Feb 18 '14 at 00:21
  • So, basically, with your `Bird` image, apply a rotation to the `Graphics` content, paint the image and reset the rotation. This is why I use `Graphics#create` and `Graphics#dispose`. It creates a copy of the `Graphics` context, which I can transform as I need to, but will discard those transformations after I'm done and not effect anything else... – MadProgrammer Feb 18 '14 at 00:28
  • wow yes it totaly works now! Im not sure why since aren't we using the same object were using to draw the rest of the things...or does create() make a new Graphics2D that just draws to the same place? – Acor74u Feb 18 '14 at 00:35
  • No create makes a copy of the details of the `Graphics` context, they still share the same output, but all you are changing is the underlying properties which are used to draw to that output... – MadProgrammer Feb 18 '14 at 00:36
  • ok so it has the same fields but it is not the same exact object...like with the same hex address and stuff? – Acor74u Feb 18 '14 at 00:39
  • The copies of the `Graphics` objects point to the same "buffer" (if you want) that represents what is actually painted, but the properties that affect what is painted or how it is painted are different – MadProgrammer Feb 18 '14 at 00:45
  • lol ok I def understand it and how to use it now, I'm not exactly college educated so some of the little technical are always clear to me, thanks! – Acor74u Feb 18 '14 at 00:48