【发布时间】:2014-08-19 17:48:01
【问题描述】:
我在使用 Java2D 绘制可能数十万个矩形时遇到问题。
起初我所做的事情是这样的:
private void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = bs.getDrawGraphics();
//Draw Graphics here
g.dispose();
bs.show();
}
然后我在测试后意识到,当任何超过 500 个矩形时,这非常低效,所以我认为也许将图形绘制到 BufferedImage 然后显示 BufferedImage 会更有效,所以我想出了这个。
private BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
private void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(3);
return;
}
Graphics g = image.createGraphics();
//Draw Graphics here
g.dispose();
Graphics g2 = bs.getDrawGraphics();
g2.drawImage(image, 0, 0, width, height, null);
g2.dispose();
bs.show();
}
但是,这仍然与第一种方法一样低效,我很难想出更好的方法来做到这一点,我宁愿远离 OpenGL 之类的东西。
在 500-1000 个矩形之间,它会变得非常慢,超过此范围的任何东西程序都会很快冻结。
所以看起来碰撞检测似乎是主要问题,而不是 Java2D 渲染。这就是我处理检测的方式,它检查两个矩形是否在任何一侧接触。如果有人对此有更好的方法,我将不胜感激,因为我看到这是多么低效。
public boolean collides(Entity e) {
Point2D upperLeftIn = new Point2D.Double(bounds.getX() + 1, bounds.getY());
Point2D upperRightIn = new Point2D.Double(bounds.getX() + 8, bounds.getY());
Point2D lowerLeftIn = new Point2D.Double(bounds.getX() + 1, bounds.getY() + 9);
Point2D lowerRightIn = new Point2D.Double(bounds.getX() + 8, bounds.getY() + 9);
Point2D upperLeftDown = new Point2D.Double(bounds.getX(), bounds.getY() + 1);
Point2D lowerLeftUp = new Point2D.Double(bounds.getX(), bounds.getY() + 8);
Point2D upperRightDown = new Point2D.Double(bounds.getX() + bounds.getWidth(), bounds.getY() + 1);
Point2D lowerRightUp = new Point2D.Double(bounds.getX() + bounds.getWidth(), bounds.getY() + 8);
Line2D top = new Line2D.Double(upperLeftIn, upperRightIn);
Line2D bottom = new Line2D.Double(lowerLeftIn, lowerRightIn);
Line2D left = new Line2D.Double(upperLeftDown, lowerLeftUp);
Line2D right = new Line2D.Double(upperRightDown, lowerRightUp);
if (e.bounds.intersectsLine(top)) {
return true;
}
if (e.bounds.intersectsLine(bottom)) {
return true;
}
if (e.bounds.intersectsLine(left)) {
return true;
}
if (e.bounds.intersectsLine(right)) {
return true;
}
return false;
}
【问题讨论】:
-
我有示例,仅使用 Swing 以稳定的 25fps 渲染(和动画)超过 10, 0000 个形状,没什么特别的。你能提供一个可运行的例子来说明你的问题吗?
-
您的渲染方法多久调用一次?
-
每秒 60 次。我正在编写一个小示例,稍后发布。
-
我做了一个小例子,可以毫不费力地绘制和动画 20000 个形状。这个程序还有碰撞检测和其他更新,所以我认为碰撞检测是现在让我慢下来的原因。如果您认为有更好的方法来处理它,我已经编辑了我的帖子以显示我的检测代码(它检查两个矩形是否发生碰撞)。