Реализация Polygon2D в Java 2D
Я создаю 2D-игру на Java, используя библиотеку Java2D для рисования, и мне действительно нужен объект полигона с плавающей точностью, который я могу использовать как для рисования игровых объектов, так и для обнаружения столкновений на них. К сожалению, полигональный объект Java поставляется только с точностью int, и нет эквивалентного Polygon2D, как с Rectangle и Rectangle2D. Я уже провел достаточно исследований, чтобы увидеть, что у меня есть несколько вариантов, но ни один из них не кажется очень хороший.
Использовать Path2D. Согласно публикации разработчика Java в этот форум, отсутствие Polygon2D было упущением, но его предлагаемая замена-Path2D. К сожалению, Path2D не предоставляет способ доступа к отдельным вершинам или ребрам, который мне нужен для обнаружения столкновений (в частности, мне нужно получить вектор, ортогональный каждому ребру).
реализовать свой собственный Polygon2D это реализует интерфейс формы, так что я все еще могу передать его
Graphics2D.draw(Shape)
. Похоже, это будет довольно сложно. Интерфейс Shape требует сложных методов реализации, таких какcontains(Rectangle2D)
иgetPathIterator(AffineTransform)
. ДляgetPathIterator
в частности, кажется, что для его реализации мне нужно вернуть объект типа PathIterator, но нет никаких конкретных реализаций интерфейса PathIterator, доступных в общедоступном AWT пакеты.Обернуть Path2d В в объекте, который "запоминает" отдельные вершины и предоставляет их клиенту. Это сработало для меня, когда мне нужна была область, которая помнила свои формы компонентов: я завернул ее в класс CompoundShape, который реализовал интерфейс Shape и перенаправил все методы Shape в их реализацию области, отслеживая каждую форму, которая была добавлена в область в ArrayList. Проблема в том, что если я следите за отдельными вершинами в двух массивах
float
s, нет никакого способа выставить их пользователю без возможности изменения пользователем вершин - и поскольку это произойдет путем прямого доступа к массиву, внутренний Path2D не будет получать уведомления об изменениях.Скопировать Полигон.java. Фактический исходный код класса Polygon Java доступен на grepcode.com, и я мог бы просто заменить связанный с вершиной
int
Сfloat
s во всем, чтобы получить Polygon2D. К сожалению, когда я попробовал это, линияimport sun.awt.geom.Crossings;
бросил ошибку компилятора, сказав: "пересечения типов недоступны из-за ограничения на требуемую библиотеку C:Program FilesJavajre7librt.jar - ... - Согласно этот вопрос это происходит потому, что лицензионное соглашение Sun запрещает вам заменять основные классы Java своими собственными, но Polygon не пытается это сделать - он просто создает объект типа sun.ОУ.геометрия.Переходы, без замены или расширение происходит, и я убедился, что моя копия Polygon находится в пакете, который не называется "java".
каков наилучший способ продолжить это? Я был бы признателен за предложения о том, как сделать один из этих вариантов работы или идею для другого варианта, который не имеет проблем, с которыми они сталкиваются.
3 ответов
Я бы также рекомендовал 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();
}
когда вы будете готовы получить фантазии, вы можете расширить это другое для поддержки квадратичных и кубических кривых. Я предполагаю, что они вам не нужны в это время, поскольку вы говорите о полигоны.
кроме того, Path2D имеет некоторые удобные статические методы для тестирования пути пересекает прямоугольник и Ли Путь содержит прямоугольник или точку. К сожалению, нет методов для тестирования пути, пересекающегося или содержащего другой путь.
можете ли вы использовать стороннюю библиотеку? Если да, могу ли я предложить использовать гладкий 2D полигон класса. Я бы сделал это внутренне, используйте этот класс для вашего фактического полигона, чтобы проверить пересечение с содержит а затем, когда вам нужно рисовать, просто бросьте float
значения int
и нарисуйте многоугольник Java2D.
Я знаю, что это может быть не оптимальное решение, но это может сработать для того, что вы делаете.
возможно, у внутренних частей многоугольника в другом масштабе?
умножить на большое число и typecast на int при записи на него, разделить на такое же большое число при чтении?