1
resposta

Solução alternativa para bola presa na raquete

Olá pessoal, tudo bom?

Eu achei interessante as várias soluções que o pessoal criou para resolver esse bug da bola presa na raquete, então eu resolvi compartilhar a minha solução também.

Então, pelo o que eu pude observar, esse bug acontece porque, dependendo da posição que a bola atinge a raquete, quando a bola é rebatida pela raquete, no próximo frame do jogo a bola continua sobrepondo o desenho da raquete. Dessa forma o jogo registra outra colisão e inverte o sentido da "velocidadeXBola" novamente e assim cria um loop de inversão do "velocidadeXBola" que só termina quando a bola sai pela lateral da raquete.

Tendo isso em mente eu fiz o seguinte:

//Variável global
let jaRebateu = false;

function verificaColisaoRaquete() {

    let colidiu = collideRectCircle(xRaquete, yRaquete, comprimentoRaquete, alturaRaquete, xBola, yBola, diametroBola);

    if (colidiu && !jaRebateu) {

        velocidadeXBola *= -1;
        jaRebateu = true;

    } else if (!colidiu && jaRebateu) {

        jaRebateu = false;

    }

}

Utilizando basicamente o mesmo código que o Prof. Guilherme escreveu nas aulas, eu fiz algumas pequenas adições, mas o segredo é a variável "jaRebateu", que eu utilizo pra controlar a quantidade de vezes que a função "verificaColisaoRaquete" realiza a inverção do "velocidadeXBola".

O que acontece aqui é que, quando a bola colide com a raquete, a função "collideRectCircle" irá definir o valor de "colidiu" para true, como foi visto nas aulas, em seguida o "if" da função irá verificar se o valor de "colidiu" é true e se a bola ainda não rebateu na raquete através do "!jaRebateu" (normalmente o valor false é o que indica isso, mas como o "if" só executa o seu código quando todas as condições dão true, eu adicionei o "!" para inverter o valor booleano da variável). Caso esse seja o primeiro frame em que ocorre essa colisão entre a bola e a raquete, o "if" deve executar seu código normalmente, invertendo o sentido de "velocidadeXBola" e também mudando o valor de "jaRebateu" para true.

Agora, se nos próximos frame a bola ainda estiver sobrepondo o desenho da raquete, o jogo irá realizar o mesmo processo de antes, porém o código do "if" que inverte o "velocidadeXBola" não será executado, pois dessa vez o valor de "jaRebateu" será true e quando o "if" verificar o "!jaRebateu", resultará false.

Por fim, depois que a bola deixar de colidir com a raquete, o jogo irá validar um outro "if", o qual verifica se não há mais colisão através do "!colidiu" e se o "jaRebateu" ainda está como true, executando assim um código que retorna o "jaRebateu" para o seu estado inicial.

Dessa forma, sempre que a bola colidir com a raquete, ela sempre será rebatida uma única vez, mesmo que após a rebatida a bola continue em contato com a raquete.

1 resposta

Oi oi, Julio! Como está?

Que solução sensacional! E a explicação super didática! Você tem futuro como instrutor, olha!

Parabéns e muito obrigada por compartilhar conosco essa belíssima solução, a ideia da flag deixou o código clean e bastante inteligente.

Obrigada novamente e continue estudando, pois seu futuro na área será brilhante!

Um forte abraço e bons estudos!