esempio di movimento a 360 gradi in java


È possibile effettuare semplicemente un movimento a 360 gradi in java (swing) senza alcun motore di gioco? tutto quello che ho è questo tentativo:

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

}

Come si può vedere nella seguente immagine, non so come gestire il movimento rotante, questo è l'output:

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

Author: David Conrad, 2014-11-22

4 answers

Cambia alcune righe...

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

Non sei sicuro di cosa stavi cercando di codificare lì, ma questa è la formula corretta per un movimento circolare.

 0
Author: laune, 2014-11-22 12:36:14

In realtà, questo è del tutto possibile.

Il mio modo preferito è quello di sfruttare effettivamente la trasformazione Graphics in modo da non dover eseguire alcun calcolo, è tutto lasciato a Graphics

A proposito:

  • poiché non hai creato l'oggetto Graphics, non disporlo mai.
  • sovrascrive paintComponent() anziché paint()
  • È sempre un buon modello chiamare super.paintComponent()

Piccolo esempio demo:

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

}
 3
Author: Guillaume Polet, 2014-11-22 12:54:24

Per calcolare la rotazione attorno a un punto, è necessario un punto centrale per la rotazione (cx, cy), il raggio o la distanza del punto dal centro, è necessario l'angolo (in radianti, non gradi), ed è necessario utilizzare seno e coseno per calcolare l'offset del punto dal centro mentre ruota attorno ad esso.

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
Author: David Conrad, 2014-11-22 12:42:13

Il programma ha alcuni problemi:

int x = 300;
int y = 500;

È necessario utilizzare un tipo di dati in virgola mobile come double per memorizzare le coordinate. Puoi lanciarli su int quando vuoi disegnarli. Se li memorizzi in int, perderai precisione.

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

Questo non funziona, poiché y viene decrementato invece di essere calcolato usando Math.sin(angle). (us Math.cos per x)

Questo è il tuo codice fisso (le parti invariate sono omesse):

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

Questa corrente disegna il cerchio in senso antiorario. Se vuoi disegnarlo in senso orario, cambia l'angolo in:

angle += 0.1;
 0
Author: Tom, 2014-11-22 12:53:33