7
respostas

Solução: adversário errar + bolinha não ficar presa

Oi gente,

Vim compartilhar uma solução que encontrei para fazer o adversario errar eventualmente e para que a bolinha não fique presa atrás da raquete.

Pra questão do adversário, fiz uma função que considera o número de colisões (tanto em bordas quanto com as raquetes) e a proporção de pontos meus e do oponente:

if (meusPontos + pontosAdversario == 0 )  {
     vyAdversario = (yBolinha - yAdversario -altura/2)+contaColisao}

  else { 
   vyAdversario = (yBolinha - yAdversario - altura/2) + contaColisao * (pontosAdversario/(meusPontos+pontosAdversario)) - meusPontos + pontosAdversario}

 yAdversario += vyAdversario;

Achei essa solução interessante porque a chance de erro do adversario se adapta ao desempenho do jogador ao longo da partida.

Em relação ao problema da bolinha ficar presa atrás da raquete, encontrei uma solução que considera o vetor da velocidade da bolinha, pois o problema ocorre quanto a bolinha muda de direção estando atrás das raquetes. Então coloquei um condicional no if para que o vxBolinha mude de direção somente quando o vx for positivo, no caso da raquete do adversario, ou negativo, no caso da minha raquete:

function colisaoRaquetes(){

  if (xBolinha - raioBolinha == xRaquete + comprimento && yBolinha - raioBolinha < yRaquete + altura && yBolinha + raioBolinha > yRaquete && Math. sign(vxBolinha) == -1){vxBolinha *= -1; raquetada.play(); contaColisao += 1}

  if (xBolinha +raioBolinha >= xAdversario && yBolinha - raioBolinha <= yAdversario + altura && yBolinha +raioBolinha >= yAdversario && Math. sign(vxBolinha) == 1) {vxBolinha *= -1; raquetada.play(); contaColisao += 1}
  }

Enfim, achei essas soluções e resolvi compartilhar, caso seja útil para alguém.

Abraços,

Carol

7 respostas

Oi Carolina. Queria usar sua solução mas não entendi nada. O que o Math. sign(vxBolinha) == -1 faz?

Oi Vitor,

O Math.sign verifica se uma variável é positiva (retorna +1) ou negativa (retorna -1).

Quando a bolinha se move pra direita, o vxBolinha é positivo, quando se move pra esquerda, é negativo. Utilizando a minha raquete como exemplo, o "correto" é a bolinha bater na parte da frente com um vx negativo (se movendo pra esquerda). Porém, quando a bolinha fica presa atrás da raquete, ela bate com um vetor positivo (indo pra direita) e é isso que faz a bolinha ficar presa (ela bate na borda, bate na raquete, bate na borda, bate na raquete....).

Então, usei essa função Math.sign para que a bolinha não mude de direção quando bater na raquete pela parte de trás.

Abraços,

Carol

Obrigado pela ajuda Carol! Entendi como a função colisaoRaquetes funciona e adimito que sua solução é muito melhor que a solução que eu criei para "resolver" o problema. Em relação ao seu código para fazer o oponente errar, se você pudesse me explicar melhor qual foi a linha de raciocínio utilizada neste código eu agradeceria.

Obrigada Vitor, que bom que gostou da solução :)

A respeito do código para fazer o oponente errar, eu criei uma variável que conta o numero de vezes que a bolinha colidiu com as bordas ou com a raquete (contaColisao) como uma forma de medir o progresso do jogo. O adversario começa com uma chance de erro = 0 e essa chance vai aumentando conforme o contador de colisões aumenta, mas considera também a discrepância entre os meus pontos e o do adversario. Conforme eu vou perdendo, essa chance vai aumentando, e vice - versa.

O valor que utilizei como chance de erro foi o número total de colisões multiplicado pela proporção de pontos do adversario, que varia entre 0 e 1. Também subtraí desse valor os meus pontos e somei os do adversario, como mais uma forma de considerar o desempenho do jogador.

Importante pontuar que essa solução funciona bem enquanto o somatório de pontos não é muito alto. Conforme a partida se prolonga indefinidamente, a tendência é que o adversario erre muito mais do que acerte. Acredito que isso poderia ser corrigido se fosse incluído algum valor dividindo a chance de erro, mas não cheguei a me aprofundar nisso. Sugestões são bem vindas :)

Abraços,

Carol

Entendi tudo agora ! Gostei muito da sua solução para evitar o bug da bolinha e em relação ao código para a "inteligência" da raquete do adversário vou ver se consigo encontrar uma forma de resolver o problema do oponente errar muito.Se descobrir algo eu te falo .Obrigado Carol! :)

Boa tarde pessoal!

Adorei o debate de vocês e me fez aprender muito.

Sobre o bug da bolinha, achei sua solução perfeita Carol, mas percebi que para aplicá-la você deixou de usar o p5.collide e eu quis tentar ajustar para manter a configuração.

No meu caso acabou ficando assim:

function colisaoRaquete(x,y){
  hit = collideRectCircle(x, y, wRaquete, hRaquete, xBolinha, yBolinha, diametro)
  if (hit == true && x == xRaquete1 && Math. sign(velocidadeXBolinha) == -1){
    velocidadeXBolinha *= -1
    raquetada.play()
  }
  if (hit == true && x == xRaquete2 && Math. sign(velocidadeXBolinha) == 1){
    velocidadeXBolinha *= -1
    raquetada.play()
  }
}

Acredito que ainda dê pra melhorar o código, mas quis compartilhar com vocês porque me parece também resolveu o bug da bolinha atrás da raquete e consegui manter o uso do p5.collide!

Além disso, sobre a questão da dificuldade, eu também me inspirei nas ideias de vocês!

Assim como a Carol, criei um contador de colisão. Aproveitei a função verificaColisaoBorda e criei um "contadorColisao++"

Na função do placar, também incluí uma gestão desse contador, para cada ponto ele ser revisto. Caso o jogador faça ponto, o contador zera, caso seja o Player2, daí o contador é divido por 2.

function marcaPonto(){
  if (xBolinha > 590){
    pontosPlayer1++
    contadorColisao = 0
    ponto.play()
  }

  if (xBolinha < 10){
    pontosPlayer2++
    contadorColisao /= 2
    ponto.play()
  }
}

Depois eu criei uma variavel "dificuldade" sem valor inicial e ajustei a função de movimento da raquete 2 e ficou assim:

function movimentaRaquete2(){
  velocidadeYOponente = yBolinha - yRaquete2 - hRaquete/2 - dificuldade
  yRaquete2 += velocidadeYOponente
  if (pontosPlayer2 > pontosPlayer1){
    dificuldade = ((pontosPlayer2 - pontosPlayer1) * 2) + contadorColisao
  } else {
    dificuldade = contadorColisao * 2  - (pontosPlayer1 - pontosPlayer2) * 2
  }
}