在Java 2D中实现Polygon2D

我正在使用Java2D库在Java中创建一个2D游戏,我真的需要一个浮点精度的Polygon对象,我可以用它来绘制游戏对象并对它们进行碰撞检测。 不幸的是,Java的Polygon对象只有int精度,并且没有像Rectangle和Rectangle2D那样的Polygon2D。 我已经做了足够的研究,看到我有一些选择,但它们似乎都不是很好。

  1. 使用Path2D 。 据该论坛的一位Java开发人员称,缺少Polygon2D是一种疏忽,但其建议的替代品是Path2D。 不幸的是,Path2D没有提供访问其各个顶点或边的方法,这是我进行碰撞检测所需要的(具体来说,我需要获得与每条边正交的矢量)。

  2. 实现我自己的Polygon2D实现Shape接口,这样我仍然可以将它传递给Graphics2D.draw(Shape) 。 这看起来很难。 Shape接口需要棘手的实现方法,如contains(Rectangle2D)getPathIterator(AffineTransform) 。 特别是对于getPathIterator ,似乎为了实现它,我需要返回一个PathIterator类型的对象,但是公共AWT包中没有可用的PathIterator接口的具体实现。

  3. 在一个“记住”各个顶点并将它们提供给客户端的对象中包裹Path2D 。 当我需要一个记住其组件形状的区域时,这对我有用:我将它包装在一个实现Shape接口的CompoundShape类中,并将所有Shape方法转发给Area的实现,同时跟踪添加到其中的每个Shape。 ArrayList中的区域。 这个问题是,如果我跟踪float s的两个数组中的各个顶点,就没有办法将它们暴露给用户而没有用户更改顶点的可能性 – 并且因为直接数组访问会发生这种情况,内部Path2D不会收到有关更改的通知。

  4. 复制Polygon.java 。 Java的Polygon类的实际源代码可以在grepcode.com上找到,我可以简单地用float s替换与顶点相关的int ,以获得Polygon2D。 不幸的是,当我尝试这个时,行import sun.awt.geom.Crossings; 抛出编译器错误,说“由于对所需库C:\ Program Files \ Java \ jre7 \ lib \ rt.jar的限制,无法访问类型交叉”。 根据这个问题 ,因为Sun的许可协议会阻止您用自己的Java类替换核心Java类,但Polygon不会尝试这样做 – 它只是创建了一个类型为sun.awt.geom.Crossings的对象,没有替换或扩展发生了,我确保将我的Polygon副本放在一个名为“java”的包中。

进行此操作的最佳方法是什么? 我很欣赏这些选项中的一个如何工作的建议,或者对于没有遇到这些问题的另一个选项的想法。

我也推荐Path2D 。 GeneralPath是一个遗留类; 不要使用它。

Path2D确实提供了对顶点值的访问,尽管它是一种迂回的方式。 您需要使用PathIterator :

 PathIterator pi = path.getPathIterator(null); float[] value = new float[6]; float x = 0, y = 0; while (!pi.isDone()) { int type = pi.currentSegment(values); if (type == PathIterator.SEG_LINETO) { x = values[0]; y = values[1]; } else if (type == PathIterator.SEG_CLOSE) { x = 0; y = 0; } else { // SEG_MOVETO, SEG_QUADTO, SEG_CUBICTO } pi.next(); } 

当你准备好开心时,可以扩展其他function以支持二次曲线和三次曲线。 我假设你在谈论多边形的时候并不需要那些。

此外,Path2D有一些方便的静态方法,用于测试路径是否与矩形相交以及路径是否包含矩形或点。 遗憾的是,没有方法可以测试相交或包含其他路径的路径。

你能用第三方图书馆吗? 如果是这样,我可以建议使用Slick 2D Polygon类。 我要做的是在内部,使用此类为您的实际Polygon检查与contains的交集,然后当您需要绘制时,只需将float值转换为int并绘制Java2D Polygon。

我知道这可能不是最佳解决方案,但它可能适用于您正在做的事情。

也许多边形的内部有不同的尺度?

在写入时,将大数乘以和类型转换为int,在读取时除以相同的大数?