我试图让一系列矩形围绕它们各自的中心旋转并向右移动,但是由于平面包含所有矩形,所有矩形围绕最新添加的矩形的中心一致旋转,而不是围绕它们各自的中心独立旋转。以下是代码:
主程序:
import java.awt.Graphics2D;
import java.util.ArrayList;
public class Rectangles {
public static final int SCREEN_WIDTH = 400;
public static final int SCREEN_HEIGHT = 400;
public static void main(String[] args) throws Exception {
Rectangles game = new Rectangles();
game.play();
}
public void play() {
board.setupAndDisplay();
}
public Rectangles() {
board = new Board(SCREEN_WIDTH, SCREEN_HEIGHT, this);
rectangle_2 = new Rectangle_2();
rectangles = new ArrayList<Rectangle_2>();
}
public void drawRectangles(Graphics2D g, float elapsedTime) {
ticks++;
if (ticks % 4000 == 0) {
Rectangle_2 rectangle = new Rectangle_2();
rectangles.add(rectangle);
}
rotateRectangles(g);
drawRectangles(g);
moveRectangles(elapsedTime);
for (int i = 0; i < rectangles.size(); i++) {
Rectangle_2 rectangle = rectangles.get(i);
if (rectangle.getX() < -75) {
rectangles.remove(i);
i--;
}
}
}
public void drawRectangles(Graphics2D g) {
for (Rectangle_2 rectangle: rectangles) {
rectangle.drawRectangle(g);
}
}
public void rotateRectangles(Graphics2D g) {
for (Rectangle_2 rectangle: rectangles) {
rectangle.rotateRectangle(g);
}
}
public void moveRectangles(float elapsedTime) {
for (Rectangle_2 rectangle: rectangles) {
rectangle.move(10 * elapsedTime);
}
}
private Board board;
private Rectangle_2 rectangle_2;
private int ticks = 0;
private ArrayList<Rectangle_2> rectangles;
}
矩形类:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Rectangle_2 {
public Rectangle_2() {
x = 0;
y = 200;
rectangle = new Rectangle((int) x, (int) y, 25, 25);
}
public void drawRectangle(Graphics2D g) {
g.setColor(Color.red);
g.draw(rectangle);
}
public void rotateRectangle(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
angle += 0.001;
g2.rotate(angle, rectangle.getX() + rectangle.getWidth() / 2, rectangle.getY() + rectangle.getHeight() / 2);
g2.setColor(Color.red);
}
public void move(float elapsedTime) {
x = x + elapsedTime;
rectangle.setLocation((int) x, (int) y);
}
public boolean collides(Rectangle r) {
return r.intersects(rectangle);
}
@Override
public String toString() {
return "Pipe [x = " + x + ", y = " + y + ", rectangle = " + rectangle + "]";
}
public Rectangle getRectangle() {
return rectangle;
}
public double getX() {
return x;
}
private double x;
private double y;
private double angle = 0;
private Rectangle rectangle;
}
动画发生的板类:
import java.awt.*;
import javax.swing.*;
public class Board extends JPanel {
private static final long serialVersionUID = 1L;
public Board(int width_, int height_, Rectangles simulator_) {
width = width_;
height = height_;
game = simulator_;
lastTime = -1L;
}
public void setupAndDisplay() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new JScrollPane(this));
f.setSize(width, height);
f.setLocation(200, 200);
f.setVisible(true);
this.setFocusable(true);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
boolean first = (lastTime == -1L);
long elapsedTime = System.nanoTime() - lastTime;
lastTime = System.nanoTime();
g.setColor(Color.white);
g.fillRect(0, 0, width, height);
g.setColor(Color.white);
game.drawRectangles((Graphics2D) g, (first ? 0.0f : (float) elapsedTime / 1e9f));
repaint();
}
private int width;
private int height;
private long lastTime;
private Rectangles game;
}
请注意,由于实现了延迟,矩形需要几秒钟才能出现。谢谢:)。
Graphics
上下文是共享资源,也就是说,在单个绘制周期中,所有组件都获得相同的Graphics
上下文。您对Graphics
上下文所做的任何更改也会得到维护(或在相同转换的情况下复合)。因此,这意味着,每次调用Graphics#rotate
时,您实际上是在复合任何可能在其上执行的先前旋转。
您需要通过两种方式更改代码…
Graphics
上下文的本地副本比如说…
矩形
成为主要的驱动程序/引擎。它负责管理实体并在每个周期更新它们。通常,我会使用某种接口
来描述其他情况下可能能够使用的功能,但你明白了
public class Rectangles {
public static void main(String[] args) throws Exception {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Rectangles game = new Rectangles();
game.play();
}
});
}
public void play() {
Board board = new Board(this);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(board);
f.pack();
f.setLocation(200, 200);
f.setVisible(true);
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateRectangles();
board.repaint();
lastTime = System.nanoTime();
}
});
timer.start();
}
public Rectangles() {
rectangle_2 = new Rectangle_2();
rectangles = new ArrayList<Rectangle_2>();
}
protected void updateRectangles() {
boolean first = (lastTime == -1L);
double elapsedTime = System.nanoTime() - lastTime;
elapsedTime = (first ? 0.0f : (float) elapsedTime / 1e9f);
ticks++;
if (ticks <= 1 || ticks % 100 == 0) {
Rectangle_2 rectangle = new Rectangle_2();
rectangles.add(rectangle);
}
rotateRectangles();
moveRectangles(elapsedTime);
for (int i = 0; i < rectangles.size(); i++) {
Rectangle_2 rectangle = rectangles.get(i);
if (rectangle.getX() < -75) {
rectangles.remove(i);
i--;
}
}
}
public void drawRectangles(Graphics2D g) {
for (Rectangle_2 rectangle : rectangles) {
rectangle.drawRectangle(g);
}
}
protected void rotateRectangles() {
for (Rectangle_2 rectangle : rectangles) {
rectangle.rotateRectangle();
}
}
protected void moveRectangles(double elapsedTime) {
for (Rectangle_2 rectangle : rectangles) {
rectangle.move(10 * elapsedTime);
}
}
private long lastTime = -1L;
private Rectangle_2 rectangle_2;
private int ticks = 0;
private ArrayList<Rectangle_2> rectangles;
}
Board
只不过是一个可以渲染实体的表面
public class Board extends JPanel {
public Board(Rectangles engine) {
game = engine;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
game.drawRectangles((Graphics2D) g);
}
private Rectangles game;
}
Rectangle_2
是一个简单的信息容器,它知道如何在有机会时自行绘制。您会注意到移动和旋转方法只是更新状态,它们不做任何其他事情。
首先创建提供的Graphics2D上下文的副本,然后应用它的更改并呈现矩形,完成后,它调用dispos
来处理副本
public class Rectangle_2 {
public Rectangle_2() {
x = 0;
y = 200;
rectangle = new Rectangle((int) x, (int) y, 25, 25);
}
public void drawRectangle(Graphics2D g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.rotate(angle, rectangle.getX() + rectangle.getWidth() / 2, rectangle.getY() + rectangle.getHeight() / 2);
g2.setColor(Color.red);
g2.draw(rectangle);
g2.dispose();
}
public void rotateRectangle() {
angle += 0.001;
}
public void move(double elapsedTime) {
x = x + elapsedTime;
rectangle.setLocation((int) x, (int) y);
}
public boolean collides(Rectangle r) {
return r.intersects(rectangle);
}
@Override
public String toString() {
return "Pipe [x = " + x + ", y = " + y + ", rectangle = " + rectangle + "]";
}
public Rectangle getRectangle() {
return rectangle;
}
public double getX() {
return x;
}
private double x;
private double y;
private double angle = 0;
private Rectangle rectangle;
}