Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Bugs de colisão

https://uploaddeimagens.com.br/imagens/sem_titulo-1-jpg--1635

Boa tarde Jeferson! Testando o jogo percebi que mesmo sem o pássaro encostar nos canos as vezes acontece esse problema

public class VerificadorDeColisão {

    private Passaro passaro;
    private Canos canos;

    public VerificadorDeColisão(Passaro passaro, Canos canos) { // construtor que recebe por parametro passaro e cano
        this.passaro = passaro;
        this.canos = canos;
    }

    public boolean temColisao() { // confere se há colisão retornando o resultado do método canos.temColisao(passaro) da classe Canos
        return canos.temColisaoCom(passaro);
    }
}
public boolean temColisaoCom(Passaro passaro) {
        for (Cano cano: canos) {
            if (cano.temColisaoHorizontalCom(passaro) // confere se há colisão com o topo do cano &&
                    && cano.temColisaoVerticalCom(passaro)){ // e com a lateral do cano
                return true;
            }
        }
        return false;
    }
 public boolean temColisaoHorizontalCom(Passaro passaro) { // passaro.X (altura do passaro) + seu raio
        return this.posicao < passaro.X + passaro.RAIO;
    }

    public boolean temColisaoVerticalCom(Passaro passaro) {
        return passaro.getAltura() - passaro.RAIO < this.alturaDoCanoSuperior
                || passaro.getAltura() + passaro.RAIO > this.alturaDoCanoInferior;
    }
6 respostas

Acho que isso acontece com o cano que já passou pelo pássaro mas ainda está na tela.

Exatamente isso, ele entende que há uma colisão mesmo com o cano que já passou, como posso fazer pra ignorar o teste de colisão só com os canos que já passaram?

Olá Christoferson,

Muito boa a sua observação, de fato tem um erro na lógica da colisão. Vamos analisar a linha que faz a verificação da colisão horizontal:

return this.posicao < passaro.X + passaro.RAIO;

O que estamos fazendo nessa linha é medir a distância entre o pássaro e o cano atual. Se essa distância for menor que o raio do pássaro então isso quer dizer que o pássaro está muito perto (talvez até dentro do cano já) então devolvemos true e a colisão acontece.

Agora o problema desse cálculo é que ele considera que o pássaro esteja sempre a esquerda do cano. Quase sempre isso é verdade, o único momento onde essa verificação falha é justamente no caso que você mostrou. Quando o cano já passou e o pássaro está a direita. Nesse caso, a distância entre o pássaro e o cano vai ser negativa (posição do cano - passaro.X) e portanto essa quantia vai ser sempre menor que o raio do pássaro! Isso vai disparar a colisão horizontal sempre que o cano estiver à esquerda do pássaro.

Para corrigir, vamos calcular a distância de forma absoluta, desconsiderando o sinal da distância (vai ser sempre positiva). Para isso, vamos mudar a linha da colisão horizontal para:

return Math.abs(this.posicao - passaro.X) < passaro.RAIO;

Pronto! Agora é só fazer o teste e tudo deve funcionar como esperamos!

Boa tarde Jeferson! Obrigado pela resposta. Substituindo o trecho antigo pelo Math.abs resolveu esse problema mas acabou criando outro bug . https://uploaddeimagens.com.br/imagens/sem_titulo-1-jpg--1642 Realmente ele corrige o defeito anterior mas agora é possível atravessar a "ponta" do cano sem colidir. Acredito que tenha que ser uma solução do tipo quando se verifica se o cano saiuDaTela(), ou seja, contando a larguraDoCano, quando o canto direito do cano ultrapassar totalmente o raio do pássaro aí sim ignorar a colisão. Já tentei mas não consigo resolver isso.

solução!

Verdade, testei aqui e realmente tá acontecendo isso.

Na colisão horizontal só estamos checando com a colisão do pássaro com o lado esquerdo do cano! Pra corrigir isso, vamos modificar a condição da colisão horizontal pra ficar assim:

        return passaro.X - Passaro.RAIO < this.posicao + LARGURA_DO_CANO &&
                passaro.X + Passaro.RAIO > this.posicao;

O que estamos fazendo agora é verificando se o lado esquerdo do pássaro está à esquerda do lado direito do cano e se o lado direito do pássaro está à direita do lado esquerdo do cano. É meio confuso mas com essa condição estamos garantindo que só vai haver colisão horizontal se alguma parte do pássaro estiver entre o lado esquerdo e direito do cano.

Valeu Jeferson! Testei várias vezes todas as formas de colidir e todas funcionam só para os canos que ainda estão a frente do pássaro, desse jeito é possível jogar com o pássaro mais no meio da tela sem problemas com os canos que já passaram. Não sei se conseguiria chegar nessa lógica sozinho, um problema de aparência simples acabou sendo bem trabalhoso de tratar, mas obrigado!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software