Problema com detecção do intersect num jogo 2D

2 respostas
alllright

Boas pessoal,

Estou aqui com um problema numa animação de um jogo, para detectar a intersecção entre um míssil (rectangle2D) e um planeta (ellipse2D) que sofreu uma transformação geométrica (rotação) e está a rodar em torno do sol.

Aqui tenho parte do código em questão, para seguirem a sequência:

... ... ...
class GamePanel extends JPanel implements Runnable, KeyListener
{
   //...
   //...
   Rectangle rectMissile = new Rectangle(missilePath, 300, 80, 10);
   Ellipse2D elliMars = new Ellipse2D.Double(MARS_CENTER_X, MARS_CENTER_Y, 25, 25);
   Ellipse2D elliMercury = new Ellipse2D.Double(MERCURY_CENTER_X, MERCURY_CENTER_Y, 15, 15);
   //...
   //...
}

public void paintComponent(Graphics g)
{
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        //...
        //...
        g2.setColor(Color.YELLOW);
        g2.fill(rectMissile);
        //...
        //...
        Antarctic an = new Antarctic(220, 510);
        g2.translate(70, 0);
        continentTx.setToRotation(Math.PI / 8.5);
        g2.scale(0.9, 0.9);
        Shape shape3 = continentTx.createTransformedShape(an);
        g2.setPaint(gradient2);
        g2.fill(shape3);
        //...
        //...

        //******        Agora a parte importante       ******
        //...
        //...
        //Translation to the center of the sun (to make planets orbit around it)
        g2.translate(800, 325);

        //Planet geometric transformations and drawing
        AffineTransform planetTx = new AffineTransform();
        
        planetTx.rotate(marsTetaAngle / 90);
        Shape marsShape = planetTx.createTransformedShape(elliMars);
        g2.setColor(new Color(150, 0, 100));
        g2.fill([b]marsShape[/b]);

        planetTx.setToRotation(mercuryTetaAngle / 60);
        Shape mercuryShape = planetTx.createTransformedShape(elliMercury);
        g2.setColor(new Color(100, 150, 0));
        g2.fill([b]mercuryShape[/b]);

        if ([b]mercuryShape[/b].intersects(rectMissile)|| [b]marsShape[/b].intersects(rectMissile))
        {
            lost = true;

            reset();
        }
}

Ora aqui é que não estou a conseguir detectar nada. O rectângulo (rectMissile) passa "por cima" dos planetas (mercuryShape ou marsShape).

Eu já tentei fazer esta rotação com coordenadas polares matemáticamente e funcionou direito, pois aí ñ é preciso criar nenhuma rotação afim no java, pois ela é feita á mão matemáticamente e nessa altura a detecção que eu fiz foi feita da seguinte forma e funcionou direito:

//...
    fill([b]elliMercury[/b]);
    //...
    fill([b]elliMars[/b]);
    if (elliMercury.intersects(rectMissile)|| elliMars.intersects(rectMissile))
    {
            lost = true;

            reset();
    }
}

O problema é que isto é para uma cadeira de universidade e o professor quer que apliquemos uma rotação da outra forma, com transformação afim e não calculada matemáticamente por coordenadas polares.

Reparam que aqui estou a desenhar e a testar DIRECTAMENTE as shapes criadas lá em cima enquanto da forma que o professor quer, temos que usar:

AffineTransform planetTx = new AffineTransform();
    //...
    //...
    Shape mercuryShape = planetTx.createTransformedShape(elliMercury);

e o fill (o desenho) já passa a ser não do elliMercury ou elliMars mas sim da shape transformada pelo AffineTransform (mercuryShape ou marsShape)

Não sei se o erro estará por aqui mas já tentei dar voltas a isto e não consigo resolver.

Sendo a rotação afim interna aplicada directamente sobre as shapes e não sendo necessário actualizar as coordenadas x e y de cada planeta em todo o instante (como o era no calcula pelas coordenadas polares), eu pergunto se o problema tb poderá estar aí, visto que usando este método AffineTransform para transformar a shape planeta apenas necessito de passar o ângulo que quero que o plaeta rode em torno do sol e actualizar esse ângulo com a velocidade do planeta e isso eu já faço numa função para o efeito:

public void marsIssues()
    {
        if (elliMars.intersects(rectMissile)) //Reset the game if missile hits planet mars
        {
            lost = true;

            reset();
        }
      
        marsTetaAngle = marsTetaAngle + marsSpeed; //Ângulo do planeta a ser actualizado com a velocidade
    }

    public void mercuryIssues()
    {
        if (elliMercury.intersects(rectMissile)) //Reset the game if missile hits planet mercury
        {
            lost = true;

            reset();
        }
        
        mercuryTetaAngle = mercuryTetaAngle + mercurySpeed; //Ângulo do planeta a ser actualizado com a velocidade
    }

Eu aqui até testo de novo a intersecção entre missil e planeta, mas em vão, pois tb ñ funciona.

Estas duas funções (além de outras) são depois chamadas no run() para serem executadas em loop pois é um jogo..

Basicamente o que eu quero testar é a colisão entre os planetas (ellipses2D que sofreram a transformação afim e que giram em torno do sol, constantemente) e o míssil (rectângulo2D que é disparado e fica também em movimento..)

Podem me ajudar por favor? Parece complicado mas não é acho eu... :roll:

Abraço à comunidade,

J Amorim
Portugal

2 Respostas

M

Bem vindo ao fórum! :slight_smile:

Antes de mais nada, vou pedir que use as tags e em torno do teu código para que se torne legível.

Assim que fizer isso, poderemos analisar melhor teu código.

alllright

Ah ok, desculpem não sabia! já adicionei as tags… :slight_smile:
Obrigado.

Criado 12 de dezembro de 2009
Ultima resposta 12 de dez. de 2009
Respostas 2
Participantes 2