2012-07-13 18 views
9

Estoy creando un juego 2D en Java usando la biblioteca Java2D para dibujar, y realmente necesito un objeto Polygon de precisión flotante que pueda usar tanto para dibujar objetos de juego como para hacer detección de colisión en ellos . Desafortunadamente, el objeto Polígono de Java viene con precisión interna solamente, y no hay un Polygon2D equivalente al que hay con Rectángulo y Rectángulo2D. Ya hice suficiente investigación para ver que tengo algunas opciones, pero ninguna de ellas parece muy buena.Implementando Polygon2D en Java 2D

  1. Uso Path2D. Según un desarrollador de Java publicando en this forum, la falta de Polygon2D era un descuido, pero su reemplazo sugerido es Path2D. Desafortunadamente, Path2D no proporciona una forma de acceder a sus vértices o bordes individuales, que necesito para realizar la detección de colisiones (específicamente, necesito obtener un vector ortogonal para cada borde).

  2. práctica mi propia Polygon2D que implementa la interfaz Forma de manera que todavía puedo pasarlo a Graphics2D.draw(Shape). Parece que sería bastante difícil. La interfaz Shape requiere métodos difíciles de implementar, como contains(Rectangle2D) y getPathIterator(AffineTransform). Para getPathIterator en particular, parece que para implementarlo necesitaría devolver un objeto de tipo PathIterator, pero no hay implementaciones concretas de la interfaz PathIterator disponible en los paquetes AWT públicos.

  3. Ajustar Path2D en un objeto que "recuerda" los vértices individuales y los proporciona al cliente. Esto funcionó para mí cuando necesitaba un Área que recordara sus formas componentes: la envolví en una clase CompoundShape que implementó la interfaz Shape y reenvió todos los métodos Shape a la implementación del Área, al mismo tiempo que seguí la pista de cada Shape que se agregó al Área en una ArrayList. El problema con esto es que si sigo los vértices individuales en dos matrices de float s, no hay forma de exponerlas al usuario sin la posibilidad de que el usuario cambie los vértices, y dado que eso ocurriría mediante acceso directo a la matriz. , el Path2D interno no sería notificado de los cambios.

  4. Copie Polygon.java. El código fuente real de la clase Polygon de Java está disponible en grepcode.com, y simplemente podría reemplazar el int s relacionado con vértices con float s para obtener un Polygon2D. Desafortunadamente, cuando probé esto, la línea import sun.awt.geom.Crossings; arrojó un error de compilación que decía "El tipo Cruces no es accesible debido a la restricción en la biblioteca requerida C: \ Archivos de programa \ Java \ jre7 \ lib \ rt.jar". De acuerdo con this question que sucede porque el acuerdo de licencia de Sun le impide reemplazar las clases de Java centrales con las suyas, pero Polygon no intenta hacerlo; simplemente crea un objeto de tipo sun.awt.geom.Crossings, no se reemplaza ni se extiende. , y me aseguré de poner mi copia de Polygon en un paquete que no se llama "java".

¿Cuál es la mejor manera de proceder con esto? Agradecería las sugerencias sobre cómo hacer que una de estas opciones funcione o una idea para otra opción que no tenga los problemas que enfrentan.

+0

Buscando [java Polygon2D] (https://www.google.com/search?q=java+polygon2d&ie=utf-8&oe=utf-8&client=ubuntu&channel=fs) en google me dio [este sitio] (http : //www.koders.com/java/fid058B5904198EB5BA18B9B086CC3B953F96CD2750.aspx) que es un 'Polygon2D' que usa precisión doble. – dacwe

+1

Parece que el código Polygon2D también usa sun.awt.geom.Crossings, por lo que tendría los mismos problemas que mi intento de copiar 'Polygon' y cambiarlo para usar' float's. – Edward

Respuesta

5

También recomendaría Path2D. GeneralPath es una clase heredada; no lo uses

Path2D proporciona acceso a los valores de los vértices, aunque sea una rotunda manera.Es necesario utilizar un 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(); 
} 

Cuando esté listo para conseguir la suposición, puede ampliar esa persona para apoyar las curvas cuadráticas y cúbicas. Supongo que no los necesita en este momento, ya que está hablando de polígonos.

Además, Path2D tiene algunos métodos estáticos útiles para comprobar si la ruta intersects es un rectángulo y si la ruta contains es un rectángulo o un punto. Lamentablemente, no hay métodos para probar una ruta que se cruza o que contiene otra ruta.

+1

Probé la intersección y la contención Path2D/Path2D iterando sobre cada segmento de una ruta y, para cada segmento, iterando sobre cada segmento de la otra ruta. Es O (n^2), pero creo que es inevitable. Para cada dos segmentos (uno de cada camino), pruebo la intersección. Si no hay intersección entre dos segmentos, probé un punto de cada ruta contenida dentro de la otra. Si ambas pruebas fallan, ninguna ruta se cruza, ni encierra, la otra. –

0

¿Se puede utilizar una biblioteca de terceros? Si es así, podría sugerir utilizar la clase Slick 2D Polygon. Lo que haría es internamente, use esta clase para su Polígono real para verificar la intersección con contains y luego cuando necesite dibujar, simplemente eche los valores float a int y dibuje el Polígono Java2D.

Sé que esta podría no ser la solución óptima, pero podría funcionar para lo que está haciendo.

0

Quizás tenga las partes internas del polígono en una escala diferente?

¿Multiplicar por un número grande y encasillar a int al escribir en él, dividir por el mismo número grande al leer?