Пример движения на 360 градусов в java

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

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


person Pink    schedule 22.11.2014    source источник
comment
Я не занимаюсь 3D-графикой, проверьте изображение.   -  person Pink    schedule 22.11.2014


Ответы (4)


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

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

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

person laune    schedule 22.11.2014

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

Я предпочитаю использовать преимущества преобразования 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);
            }
        });
    }

}
person Guillaume Polet    schedule 22.11.2014

Чтобы вычислить вращение вокруг точки, вам нужна центральная точка для вращения (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
person David Conrad    schedule 22.11.2014

Ваша программа имеет некоторые проблемы:

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;
person Tom    schedule 22.11.2014
comment
Это неправильно, потому что угол должен быть в радианах, а косинус идет с х, а синус идет с у. Также нормально иметь x и y как ints, но ваш код будет вращать x и y вокруг точки (0, 0). - person David Conrad; 22.11.2014
comment
@DavidConrad but your code will be rotating x and y around the point (0, 0) Он будет вращаться вокруг начальной координаты x и y. И вы правы, sin и cos в настоящее время поменялись местами. - person Tom; 22.11.2014
comment
Извините, я пропустил, что вы использовали +=. - person David Conrad; 22.11.2014
comment
@DavidConrad Вот почему я использовал double: P. Вы использовали для этого отдельную переменную. Но я обычно предпочитаю хранить координаты с использованием типа данных с плавающей запятой, даже в пиксельных системах. - person Tom; 22.11.2014