我在发布后的几分钟内找到了解决方案,但由于声誉不佳,我无法删除帖子
为了好玩,我决定开始研究可能在某些时候变成游戏的东西。
我试图绘制一些圆圈并将它们移动到当前给定的方向。这会导致闪烁。我很可能会监督一些非常基本的东西,但我无法弄清楚它为什么不能顺利渲染。
我的董事会类看起来像(删除了我认为不必要的东西):
public class Board extends Canvas implements Runnable {
public static void main(String[] args) {
Board board = new Board();
board.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
JFrame frame = new JFrame("Circles");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(board);
frame.pack();
frame.setVisible(true);
board.start();
}
@Override
public void run() {
while (running) {
process();
repaint();
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
绘画方法:
public void paint(Graphics g1) {
super.paint(g1);
Graphics2D g = (Graphics2D) g1;
for (Ball ball : Ball.BALLS) {
g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(), ball.getRadius());
}
}
我的处理方法:
private void process() {
if (utilities.randInt(1, 100) < 10 && Ball.getBallCount() < 40) {
Ball.spawnNew(this);
}
for (Ball ball : Ball.BALLS) {
ball.move(this);
}
Ball.BALLS.removeAll(Ball.TO_REMOVE);
Ball.TO_REMOVE.clear();
}
每次调用时,移动方法基本上会将球的x值增加一个给定的值(向右移动)。
就像我说的那样,我不确定为什么它会闪烁,所以如果你有任何指示,请告诉我们。
谢谢!
答案 0 :(得分:1)
这听起来像是需要执行双缓冲的情况,因此在更新另一个时,可以保留一个画布副本。
你在这里使用AWT,我不知道如何用AWT手动实现双缓冲。但是,如果你愿意在这里使用Swing,你可以利用自动双缓冲。请参阅有关How to make canvas with Swing?的问题以及Oracle技术网关于Painting in AWT and Swing的文章。
基本理念是:
paint(Graphics)
时,你现在从javax.swing.JComponent而不是java.awt.Component覆盖它)super(true)
创建一个构造函数以启用双缓冲。修改:另外,as iccthedral points out,您最好覆盖paintComponent(Graphics)
,并包括对super.paintComponent(Graphics)
的调用。请参阅Difference between paint, paintComponent and paintComponents in Swing。
答案 1 :(得分:1)
你需要双缓冲。为此,您需要创建BufferedImage
并从中获取Graphics
。将所有内容绘制到图像上,将图像渲染到屏幕上,然后最终使用背景颜色或图像填充图像以重置图像。
样品:
//one time instantiation
BufferedImage b = new BufferedImage(width, height, mode);
在paint(Graphics g)
:
Graphics buffer = b.getGraphics();
//render all of the stuff on to buffer
Graphics2D g = (Graphics2D) buffer;
for (Ball ball : Ball.BALLS) {
g.drawOval((int) ball.getLocation().getX(), (int) ball.getLocation().getY(), ball.getRadius(), ball.getRadius());
}
g1.drawImage(b, 0, 0, width, height, null);
g.setColor(Color.BLACK);
//reset the image
g.drawRect(0, 0, width, height);
g.dispose();