Пример поворота на 360 градусов в Яве

1

можно ли просто сделать 360-градусное движение в java (swing) без какого-либо игрового движка? все, что у меня есть, это попытка:

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) {}
    }
    }

}

как вы можете видеть на следующем рисунке, я не знаю, как обращаться с вращающимся движением, это результат:

изображение http://screenshot.cz/GOXE3/mvm.jpg

  • 0
    Я не делаю 3D-графику, проверьте изображение.
Теги:
swing
rotation
rotateanimation

4 ответа

0
Лучший ответ

Измените несколько строк...

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) {}
  }
}

Не уверен, что вы пытались закодировать там, но это правильная формула для кругового движения.

  • 0
    спасибо вот что я искал
3

На самом деле это вполне возможно.

Мой предпочтительный способ - фактически использовать Graphics преобразование, так что вам не нужно делать какие-либо вычисления, все это осталось на Graphics

Кстати:

  • поскольку вы не создали объект Graphics, никогда не удаляйте его.
  • переопределить paintComponent() а не paint()
  • Это всегда хороший шаблон для вызова super.paintComponent()

Маленький демонстрационный пример:

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);
            }
        });
    }

}
0

Чтобы рассчитать вращение вокруг точки, вам нужна центральная точка для вращения (cx, cy), радиус или расстояние от центра от центра, вам нужен угол (в радианах, а не градусах), и вам нужно использовать синус и косинус для вычисления смещения точки от центра, когда он вращается вокруг него.

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

У вас есть некоторые проблемы:

int x = 300;
int y = 500;

Для хранения координат вы должны использовать тип данных с плавающей точкой, например double. Вы можете направить их в int когда хотите их нарисовать. Если вы храните их в int, вы потеряете точность.

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

Это не работает, так как y уменьшается, а не вычисляется с использованием Math.sin(angle). (нас Math.cos для x)

Это ваш фиксированный код (неизменные части опущены):

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
    }
}

Этот поток вытягивает круг против часовой стрелки. Если вы хотите нарисовать его по часовой стрелке, измените угол на:

angle += 0.1;
  • 0
    спасибо за объяснение
  • 0
    Это неправильно, потому что угол должен быть в радианах, а косинус идет с x, а синус с y. Также хорошо иметь х и у в качестве ints , но ваш код будет вращать х и у вокруг точки (0, 0).
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню