Implementando o Polygon2D em Java 2D

9

Eu estou criando um jogo 2D em Java usando a biblioteca Java2D para desenhar, e eu realmente preciso de um objeto Polygon de precisão flutuante que eu possa usar tanto para desenhar objetos de jogo quanto para fazer detecção de colisão neles. Infelizmente, o objeto Polygon do Java é fornecido apenas com precisão int e não há Polygon2D equivalente, como o Rectangle e o Rectangle2D. Já fiz pesquisas suficientes para ver que tenho algumas opções, mas nenhuma delas parece muito boa.

  1. Use o Path2D . De acordo com um desenvolvedor de Java postando em este fórum , a falta de Polygon2D foi um descuido, mas sua sugestão de substituição é o Path2D. Infelizmente, o Path2D não fornece uma maneira de acessar seus vértices ou arestas individuais, o que eu preciso para fazer a detecção de colisão (especificamente eu preciso obter um vetor ortogonal para cada aresta).

  2. Implemente meu próprio Polygon2D que implementa a interface Shape para que eu ainda possa passá-lo para Graphics2D.draw(Shape) . Isso parece ser bem difícil. A interface Shape requer métodos difíceis de implementar, como contains(Rectangle2D) e getPathIterator(AffineTransform) . Para getPathIterator em particular, parece que para implementá-lo eu precisaria retornar um objeto do tipo PathIterator, mas não há implementações concretas da interface PathIterator disponível nos pacotes AWT públicos.

  3. Envolva o Path2D em um objeto que "lembre" os vértices individuais e os forneça ao cliente. Isso funcionou para mim quando eu precisei de uma área que lembrei de suas formas de componentes: agrupei em uma classe CompoundShape que implementou a interface Shape e encaminhei todos os métodos Shape para a implementação da área deles, mantendo o controle de cada Shape que foi adicionada à Área em uma ArrayList. O problema com isso é que, se eu acompanhar os vértices individuais em dois arrays de float s, não há como expô-los ao usuário sem a possibilidade de o usuário alterar os vértices - e, como isso aconteceria acesso à matriz, o Path2D interno não seria notificado das alterações.

  4. Copie Polygon.java . O código-fonte real da classe Polygon do Java está disponível no grepcode.com, e eu poderia simplesmente substituir o int s relacionado a vértices por float s para obter um Polygon2D. Infelizmente, quando eu tentei isso, a linha import sun.awt.geom.Crossings; jogou um erro do compilador dizendo "O tipo Crossings não está acessível devido à restrição na biblioteca necessária C: \ Arquivos de Programas \ Java \ jre7 \ lib \ rt.jar." De acordo com esta questão isso acontece porque o contrato de licença da Sun impede que você substitua as principais classes Java pelas suas próprias, mas o Polygon não tenta fazer isso - ele simplesmente cria um objeto do tipo sun.awt.geom.Crossings, nenhuma substituição ou extensão acontece, e eu Certifique-se de colocar minha cópia do Polygon em um pacote não chamado "java".

Qual é a melhor maneira de proceder com isso? Eu apreciaria as sugestões de como fazer uma dessas opções funcionar ou uma ideia para outra opção que não tenha os problemas encontrados.

    
por Edward 13.07.2012 в 08:36
fonte

3 respostas

7

Também recomendamos o Path2D . GeneralPath é uma classe legada; não use.

O Path2D fornece acesso aos valores do vértice, embora seja uma forma indireta. Você precisa usar um 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();
}

Quando você estiver pronto para se interessar, você pode expandir esse else para suportar as curvas quadráticas e cúbicas. Eu suponho que você não precisa deles no momento em que você está falando sobre polígonos.

Além disso, o Path2D possui alguns métodos estáticos úteis para testar se o caminho intercepta um retângulo e se o caminho contém um retângulo ou ponto. Infelizmente, não há métodos para testar um caminho que se cruze ou contenha outro caminho.

    
por Devon_C_Miller 21.08.2012 / 23:21
fonte
0

Você pode usar uma biblioteca de terceiros? Em caso afirmativo, sugiro usar a classe Slick 2D Polygon . O que eu faria internamente seria usar essa classe para o polígono real para verificar a interseção com contém e, em seguida, quando você precisa desenhar, apenas converta os valores float para int e desenhe o polígono Java2D.

Eu sei que isso pode não ser a solução ideal, mas pode funcionar para o que você está fazendo.

    
por Dan W 21.08.2012 / 23:29
fonte
0

Talvez tenha os internos do polígono em uma escala diferente?

Multiplique por um número grande e digite para o int ao escrever, divida pelo mesmo número grande ao ler?

    
por Chozabu 12.01.2013 / 07:42
fonte