360 degree movement example in java

2.9k views Asked by At

is it possible to simply make 360 degree movement in java(swing) without any game engine? all I have is this attempt:

public class Game extends JPanel implements Runnable {

    int x = 300;
    int y = 500;
    float angle = 30;
    Game game;

    public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.add(new Game());
    frame.setSize(600, 600);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public Game() { 
    setSize(600, 600);

    Thread thread = new Thread(this);
    thread.start();
    }

    @Override
    public void paint(Graphics g) {
    g.setColor(Color.WHITE);
    g.drawRect(0, 0, 600, 600);
    g.setColor(Color.CYAN);
    g.fillOval(x, y, 10, 10);
    g.dispose();
    }

    @Override
    public void run() {
    while(true) {
        angle += -0.1;
        x += Math.sin(angle);
        y--;
        repaint();
        try {
        Thread.sleep(50);
        } catch (InterruptedException ex) {}
    }
    }

}

as you can see in following picture, I don't know how to handle movement rotating, this is the output:

image http://screenshot.cz/GOXE3/mvm.jpg

4

There are 4 answers

0
laune On BEST ANSWER

Change a few lines...

int basex = 300;   // midpoint of the circle
int basey = 400;
int radius = 100;  // radius
int x;
int y;
float angle = 0;  // Angles in radians, NOT degrees!

public void run() {
  while(true) {
    angle += 0.01;
    x  = (int)(basex + radius*Math.cos(angle));
    y  = (int)(basey - radius*Math.sin(angle));
    repaint();
    try {
        Thread.sleep(50);
    } catch (InterruptedException ex) {}
  }
}

Not sure what you were trying to code there, but this is the correct formula for a circular movement.

4
Tom On

You program has some problems:

int x = 300;
int y = 500;

You should use a floating point data type like double to store the coordinates. You can cast them to int when you want to draw them. If you store them in int, you'll lose precision.

x += Math.sin(angle);
y--;

This doesn't work, since y is decremented instead of calculated using Math.sin(angle). (us Math.cos for x)

This is your fixed code (unchanged parts are omitted):

double x = 300;
double y = 500;
float angle = 30;
double radius = 10D; // new variable to increase the radius of the drawn circle
Game game;

// main method

// constructor

@Override
public void paint(Graphics g) {
    // ... stuff omitted
    g.fillOval((int)x, (int)y, 10, 10); // you can cast to int here
    g.dispose();
}

@Override
public void run() {
    while (true) {
        angle -= 0.1; // is the same as `angle += -0.1`
        x += radius * Math.cos(angle);
        y += radius * Math.sin(angle);
        repaint();
        // ... try catch block
    }
}

This currenlty draw the circle counter-clockwise. If you want to draw it clockwise, then change angle to:

angle += 0.1;
0
David Conrad On

To calculate the rotation around a point, you need a center point for the rotation (cx, cy), the radius or distance of the point from the center, you need the angle (in radians, not degrees), and you need to use sine and cosine to calculate the offset of the point from the center as it rotates around it.

int cx, cy, radius; // I'll let you determine these
double theta = Math.toRadians(30);
double dtheta = Math.toRadians(-0.1);

double dx = Math.cos(theta) * radius;
double dy = Math.sin(theta) * radius;
int x = (int)(cx + dx);
int y = (int)(cy + dy);

repaint();
theta += dtheta; // step the angle
0
Guillaume Polet On

Actually, this is quite possible.

My preferred way is to actually take advantage of the Graphics transform so that you don't have to do any computation, it's all left to the Graphics

By the way:

  • since you did not create the Graphics object, don't ever dispose it.
  • override paintComponent() rather than paint()
  • It's always a good pattern to call super.paintComponent()

Small demo example:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestRotate {

    public static class ShapeAndColor {
        private final Shape shape;
        private final Color color;

        public ShapeAndColor(Shape shape, Color color) {
            super();
            this.shape = shape;
            this.color = color;
        }

        public Shape getShape() {
            return shape;
        }

        public Color getColor() {
            return color;
        }

    }

    public static class RotatingShapesPanel extends JComponent {

        private List<ShapeAndColor> shapes;

        private double rotation = 0.0;

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            AffineTransform translate = AffineTransform.getTranslateInstance(-getWidth() / 2, -getHeight() / 2);
            AffineTransform rotate = AffineTransform.getRotateInstance(rotation);
            AffineTransform t = AffineTransform.getTranslateInstance(getWidth() / 2, getHeight() / 2);
            t.concatenate(rotate);
            t.concatenate(translate);
            g2d.setTransform(t);
            AffineTransform scale = AffineTransform.getScaleInstance(getWidth(), getHeight());
            for (ShapeAndColor shape : shapes) {
                Area area = new Area(shape.getShape());
                g2d.setColor(shape.getColor());
                area.transform(scale);
                g2d.fill(area);
            }
        }

        public void setShapes(List<ShapeAndColor> shapes) {
            this.shapes = shapes;
            repaint();
        }

        public double getRotation() {
            return rotation;
        }

        public void setRotation(double rotation) {
            this.rotation = rotation;
            repaint();
        }

    }

    protected void initUI(final boolean useBorderLayout) {
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        List<ShapeAndColor> shapes = new ArrayList<>();
        Random r = new Random();
        for (int i = 0; i < 10; i++) {
            double x = r.nextDouble();
            double y = r.nextDouble();
            double w = r.nextDouble();
            double h = r.nextDouble();
            w = Math.min(w, 1 - x) / 2;
            h = Math.min(h, 1 - y) / 2;
            double a = Math.min(w, h) / 10.0;
            RoundRectangle2D.Double shape = new RoundRectangle2D.Double(x, y, w, h, a, a);
            Color color = new Color(r.nextInt(256), r.nextInt(256), r.nextInt(256));
            shapes.add(new ShapeAndColor(shape, color));
        }
        final RotatingShapesPanel panel = new RotatingShapesPanel();
        panel.setShapes(shapes);
        frame.add(panel);
        frame.setSize(600, 600);
        frame.setVisible(true);
        Timer t = new Timer(0, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                double rotation = panel.getRotation() + 0.02;
                if (rotation > Math.PI * 2) {
                    rotation -= Math.PI * 2;
                }
                panel.setRotation(rotation);
            }
        });
        t.setRepeats(true);
        t.setDelay(10);
        t.start();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestRotate().initUI(true);
            }
        });
    }

}