CoderGuy123
CoderGuy123

Reputation: 107

Java (Swing) - How to rotate a bunch of lines?

I've been looking for this online, but I can't seem to find how to rotate a bunch of lines. I made a "plane" with the Graphics.drawLine() function, but I want to know how to rotate the whole thing 90 degrees to the right when it hits a wall. Here is my current code:

/* MovePlane
 * Moves plane to the right, down, left, up, and repeats using Timer object
 */

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;


public class MovePlane extends JPanel implements ActionListener {
   private int delay = 5;
   private Timer timer;

   private int x = 10;      // x position
   private int y = 10;      // y position

   private boolean right = true;
   private boolean up = true;

   public MovePlane() {
       timer = new Timer(delay, this);
       timer.start();       // start the timer - infinite
   }

   public void actionPerformed(ActionEvent e) {
    // will run when the timer fires
       repaint();
   }

   public void paintComponent(Graphics g) {
       // both paint and paintComponent work - difference?
       super.paintComponent(g);    // call superclass's paintComponent 
       g.drawLine(x,y,x+20,y);               // body - drawn in terms of x
       g.drawLine(x+15,y-5,x+15,y+5);    // wing
       g.drawLine(x,y-2,x,y+2);  
       if (right && up) {
            x++;
            if (x == getWidth()-25) {
                right = false;
                up = false;
            }
       } else if (!right && !up) {
            y++;
            if (y == getHeight()-10) {
                up = true;
            }
       } else {
            if (x <= getWidth()-15 && x > 0) {
                x--;
            }
            if (x == 0) {
                y--;
            }
            if (y == 10) {
                right = true;
            }
       }
    }

    public static void main(String args[]) {
        JFrame frame = new JFrame("Move Plane");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MovePlane bp = new MovePlane(); 
        frame.add(bp);
        frame.setSize(300, 300); // set frame size
        frame.setVisible(true); // display frame
    }

}

Upvotes: 1

Views: 236

Answers (1)

Frakcool
Frakcool

Reputation: 11153

You need to change it everytime you change the direction, so, you need to move your g.drawLine(...) calls inside each if conditions...

But while rotating the plane, you also need to take care of the "bounds" or the limits of the screen, so, I modified if (x == 0) and ... && x > 0 conditions to have a gap of 20 instead...

Let's start for the plane going from left to right:

g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
g.drawLine(x + 15, y - 5, x + 15, y + 5);    // wing
g.drawLine(x, y - 2, x, y + 2);

This is telling us that:

  • Your plane's body length is 20
  • Your wings are 15 units from the back
  • Your tail is right on the back

So, to change it to move from left to right, we need to invert the wings and tail positions...

  • Plane lenght is still the same
  • Wings are now 5 units from the back
  • Tail is now on the front

Then, we have this code:

g.drawLine(x, y, x + 20, y);               // Body length 20
g.drawLine(x + 5, y - 5, x + 5, y + 5);    // Wing's are 5 units from the front
g.drawLine(x + 20, y - 2, x + 20, y + 2);  // Tail is on the front (at body's length)

And for when going down:

  • Body's length is now on Y axis
  • Wings should be at 15 units from the back
  • Tail is at the back

So we have:

g.drawLine(x, y, x, y + 20);               // Body is now on Y axis
g.drawLine(x - 5, y + 15, x + 5, y + 15);    // Wings are 15 units from the back
g.drawLine(x - 2, y, x + 2, y); // Tail is on the back

And applying same logic as when going from right to left:

g.drawLine(x, y + 20, x, y);
g.drawLine(x - 5, y + 5, x + 5, y + 5);
g.drawLine(x - 2, y + 20, x + 2, y + 20);

Then your paintComponent(...) method looks like this:

public void paintComponent(Graphics g) {
    // both paint and paintComponent work - difference?
    super.paintComponent(g);    // call superclass's paintComponent
    if (right && up) {
        g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
        g.drawLine(x + 15, y - 5, x + 15, y + 5);    // wing
        g.drawLine(x, y - 2, x, y + 2);
        x++;
        if (x == getWidth() - 25) {
            right = false;
            up = false;
        }
    } else if (!right && !up) {
        g.drawLine(x, y, x, y + 20);               // body - drawn in terms of x
        g.drawLine(x - 5, y + 15, x + 5, y + 15);    // wing
        g.drawLine(x - 2, y, x + 2, y);
        y++;
        if (y == getHeight() - 25) {
            up = true;
        }
    } else {
        if (x <= getWidth() - 15 && x > 20) {
            g.drawLine(x, y, x + 20, y);               // body - drawn in terms of x
            g.drawLine(x + 5, y - 5, x + 5, y + 5);    // wing
            g.drawLine(x + 20, y - 2, x + 20, y + 2);
            x--;
        }
        if (x == 20) {
            g.drawLine(x, y, x, y + 20);               // body - drawn in terms of x
            g.drawLine(x - 5, y + 5, x + 5, y + 5);    // wing
            g.drawLine(x - 2, y + 20, x + 2, y + 20);
            y--;
        }
        if (y == 10) {
            right = true;
        }
    }
}

And that's it! Here's an image showing how it looks like:

enter image description here

Additional tips:

  1. Don't call frame.setSize() but override MovePlane's JPanel getPreferredSize() to return a fixed size of 300, 300.

  2. Always place your GUI in the Event Dispatch Thread (EDT) by wrapping your main method like this:

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                //Your code here
            }
        });
    }
    
  3. Related to tip #1, call frame.pack(); instead of frame.setSize() after overriding JPanel's getPreferredSize() :)

Upvotes: 2

Related Questions