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

Dúvida sobre a colisão com a raquete

Olá, pessoal. Estou com uma dúvida sobre a colisão com a raquete.

A condição do trecho de código "yBolinha - raio < yRaquete + raqueteAltura" consiste que o valor da posição da bolinha deve ser menor que o valor da posição da raquete, certo? No plano cartesiano desse editor, referente ao eixo Y, os valores positivos estão abaixo e os valores negativos estão acima, correto? Então, no meu entendimento, para o valor da posição da bolinha ser menor que o valor da posição da raquete, a bolinha deveria estar acima da raquete, já que quanto mais acima, menor o valor de Y, só que não foi isso o que aconteceu na prática conforme foi demonstrado na vídeo-aula. Devo estar confundindo alguma coisa. Vocês poderiam tentar me esclarecer essa questão?

Outra coisa. Para verificar a altura da raquete em cima foi feito o oposto do que foi feito para a altura da raquete embaixo só que sem levar em conta a altura da raquete? Por que não foi levado em conta a altura da raquete nesse segundo caso?

Desde já eu agradeço.

14 respostas

Oi oi, Mateus! Tudo bem com você?

Algo que confunde a gente para entender essa parte da lógica é o sistema de coordenadas do p5.js, vamos conferir?

O sistema de coordenadas do p5.js é o plano cartesiano. No entanto, a biblioteca toma como referência o 4º quadrante do plano cartesiano, que é esse na imagem abaixo:

Plano cartesiano com o 4 quadrante em destaque, demonstrando que é o quadrante utilizado pelo editor da biblioteca p5.js

E é por isso que às vezes a referência parece ser um pouco confusa, mas depois de compreender o sistema de coordenadas os valores ficam mais claros.

Já a função verificaColisaoRaquete() funciona excluindo os valores abaixo e acima da raquete, mantendo apenas a raquete para inverter a posição da bolinha após o toque.

function verificaColisaoRaquete() {
    if (xBolinha - raio < xRaquete + raqueteComprimento
        && yBolinha - raio < yRaquete + raqueteAltura
        && yBolinha + raio > yRaquete) {
        velocidadeXBolinha *= -1;
    }
}

A condição yBolinha - raio < yRaquete + raqueteAltura significa que você irá pegar a bolinha no y (sua posição na vertical) e vai subtrair pelo raio (para aumentar a sensibilidade de toque). Esses valores precisam ser menores que a soma entre a posição da Raquete no eixo y e sua Altura (pois assim vai entender que a bolinha está acima da raquete).

O terceiro caso que precisa ser verdadeiro é que a bolinha no eixo de y mais o valor do seu raio precisa ser maior que a posição y da Raquete.

Essas implementações precisam ocorrer simultâneamente para que toda a condição seja verdadeira. Sabemos isso por conta do operador lógico &&, que funciona como um "E".

Espero que tenha conseguido ajudar você, fico à disposição!

Um Abraço e bons estudos!!!

Ola Mateus, vou tentar explicar da forma como eu entendi.

Primeiro sobre a altura da raquete. Como você mesmo falou, no plano cartesiano dessa plataforma, quanto mais para baixo maior os valores. Essa lógica se aplica para os retangulos da seguinte forma: Quanto maior o retangulo, mais para baixo ele vai crescer, ou seja, os retangulos crescem para baixo, logo, se você quiser marcar a parte mais para baixo de um retangulo, você terá que somar a altura, mas, se você quiser marcar a parte superior do retangulo, teoricamente você vai estar marcando a base do retangulo (ou o pé do retangulo) por isso não precisa somar a altura.

Agora a dúvida quanto ao código. O código de colisão com a raquete mostrado na aula ele possui 3 partes. uma para delimitar o movimento no eixo "x" (a primeira parte do código), e 2 para delimitar o movimento no eixo "y". seguindo a ordem da vídeo aula, esse código que você ficou em dúvida seria a segunda parte do código completo de colisão com a raquete. Explicando por etapas do código:

xBolinha - raio < xRaquete + raqueteComprimento: esse código diz o quanto a bolinha pode andar para a esquerda antes de voltar yBolinha - raio < yRaquete + raqueteAltura: esse código delimita o limite inferior da raquete, ou seja, quando a parte superior da bolinha estiver acima da parte inferior da raquete, a bolinha obedece o limite de movimentação de eixo "x" estabelecido na primeira parte do código yBolinha + raio > yRaquete: esse código delimita o limite superior da raquete, quando a parte inferior da bolinha estiver abaixo da parte superior da raquete, a bolinha obedece a delimitação da primeira parte da função.

se as extremidades da bolinha estiverem alem dos limites delimitados por esses dois códigos, a bolinha não obedece a delimitação da primeira parte da função.

espero ter ajudado na compreenção.

Olá, pessoal.

Camila Pessoa, infelizmente a sua explicação não conseguiu me ajudar...


Ighor Bandeira, você me fez entender porque que a altura da raquete não foi levada em conta na terceira parte do código da colisão. Muito obrigado por isso, mas a segunda e terceira partes em si eu continuo sem entender...

Tipo, como assim o limite inferior da raquete é delimitado quando a parte superior da bolinha estiver acima da parte inferior da raquete se a bolinha vai estar embaixo da raquete? A mesma coisa com o limite supeior da raquete que será delimitado quando a parte inferior da bolinha estiver abaixo da parte superior da raquete, como assim se a bolinha vai estar acima da raquete?

O que está me causando essa dúvida também é esse plano cartesiano. Não estou conseguindo enxergar como que a bolinha, estando abaixo da raquete, tem um valor Y menor que a raquete sendo que nesse plano cartesiano quanto mais pra baixo, mais positivo. A mesma coisa com relação a terceira parte do código.

Poderia tentar me explicar melhor, por gentileza?

Desde já o meu muito obrigado, amigo.


Se mais alguém entendeu a minha dúvida e sente que pode explicar melhor, por favor, agradeceria muito se o fizessem.

Muito obrigado!

Mateus eu demorei bastante para entender também . Eu tive que desenhar o plano cartesiano do P5 no meu caderno e criar exemplos imaginários . Isso demorou um tempo . Infelizmente eu não vou conseguir dar uma explicação melhor que a do Ighor . Pelo menos não no momento. Vou ver se consigo achar uma maneira mais fácil de explicar e se eu encontrar eu mando aqui.

Ola Matheus, vou tentar explicar melhor a forma q eu entendi.

Quando é delimitado o limite inferior da barra, a bolinha irá colidir com tudo que estiver acima do limite inferior da barra. Se a parte superior da bilonha estiver abaixo do limite inferior da barra, então a bolinha vai estar abaixo do limite inferior da barra, ou seja, fora do limite de colisão que foi estabelecido, e portanto, não irá colidir. Porem, quando o limite superior da bolinha estiver acima do limite inferior da barra, pode ser que a bolinha esteja colidindo com a raquete, por isso a colisão é ativada nessa situação. Para que a bolinha não colida com a área alem do limite superior da barra, o limite superior é descrito também.

A mesma lógica serve para o limite superior. A área da barra é delimitada pela interação dessas duas partes.

Essa primeira imágem seria a área de colisão da tela antes dos limites serem estabelecidos. Imagem da sua raquete no pong com um retangulo vermelho vertical indo do topo a base da telaEssa segunda imágem é a área de colisão quando o limite inferior é estabelecido. Insira aqui a descrição dessa imagem para ajudar na acessibilidadeRepare que agora a bolinha apenas irá colidir quando estiver acima do limite inferior, seguindo a ideia do que eu falei antes.

A terceira imágem é a área de colisão quando definimos apenas o limite superior Insira aqui a descrição dessa imagem para ajudar na acessibilidadeO limite superior e inferior seguem a mesma lógica de limitação, quando a bolinha estiver acima do limite superior, não há colisão, a colisão só irá ocorrer quando a bolinha estiver abaixo do limite superior da raquete.

Essa ultima imágem mostra a interação dos dois códigos. Insira aqui a descrição dessa imagem para ajudar na acessibilidade Como os dois códigos devem ser obedecidos, o JS entende que a área de colisão é apenas a área de intercessão entre os dois limites. Assim a área de colisão estabelecida fica sendo do limite superior da raquete até o limite inferior.

Espero que tenha ficado mais claro assim.

Acredito que o Ighor conseguiu deixar bem mais claro agora. Não é especificamente a raquete desenhada que a bolinha irá reconhecer na colisão e sim um determinado intervalo no plano cartesiano. Ficou muito show, Ighor! Parabéns!

Só uma observação, Mateus. Como falei lá em cima, o p5.js utiliza como referência o 4ª quadrante do plano cartesiano. Quanto mais para baixo, maior o valor de y (embora seja negativo). Outro detalhe é que os desenhos no p5.js tem o seu ponto inicial o canto superior esquerdo de cada figura e não no centro (por isso que ao marcar o valor que corresponde a altura da raquete, você já compreende toda a raquete).

Obrigada, Ighor, ficou excelente mesmo! Leva jeito para instrutor :)

Olá, Ighor e Camila.

Muito obrigado pelas explicações, principalmente da parte do Ighor. Realmente deu pra ver que ele se empenhou em tentar me explicar a coisa e ficou muito bem explicado de fato, porém, admito que estou ficando com vergonha já, acho que vocês não entenderam muito bem a minha dúvida... Não é bem a parte das colisões que não estou entendendo, mas sim a matemática da coisa, digamos assim.

Quando eu estava perguntando como que a bolinha, estando abaixo da raquete, tem um valor Y menor que a raquete sendo que nesse plano cartesiano quanto mais pra baixo, mais positivo era disso que eu estava falando. Vou tentar expor a minha dúvida de outra forma usando de valores para isso.

Vamos levar em conta a parte do código na qual o limite inferior é estabelecido.

Com o intuito de tentar entender a matemática do código eu testei alguns valores diferentes. Nesse exemplo que eu vou dar eu coloquei yBolinha com o valor de 325.

O trecho do código na qual o limite inferior é estabelecido está definido como yBolinha - raio < yRaquete + raqueteAltura, ou seja, o valor de yBolinha - raio deve ser MENOR que o valor de yRaquete + raqueteAltura para que esta condição seja verdadeira e é preciso que seja verdadeira pois estamos usando o operador AND que exige que todos os operandos sejam verdadeiros para que ele seja verdadeiro.

Fazendo os cálculos nós temos:

VALORES:

yBolinha = 325 // raio = 7,5 // yRaquete = 150 // raqueteAltura = 90

CÁLCULOS:

yBolinha - raio = 325 - 7,5 = 317,5

yRaquete + raqueteAltura = 150 + 90 = 240

317,5 é MENOR que 240 ? NÃO, não é, é FALSO, mas ainda assim a colisão com a borda está acontecendo como pode ser visto na imagem abaixo:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Conseguem ver como que aparentemente isso não faz sentido? Digo aparentemente porque deve ser eu que não estou entendendo. Acredito que deva ser esse plano cartesiano estranho me pregando peças que a Camila já comentou por duas vezes.

Expus a dúvida só levando em conta o trecho de código do limite inferior porque a dúvida é a mesma quanto ao limite superior, é tudo sobre essa questão matemática, entendem?

Enfim, acredito que expus bem a minha dúvida agora e é isso que não estou entendendo... Vocês conseguem me explicar esse lado matemático do código?

Muitíssimo obrigado mesmo, pessoal!

Olá Matheus, acho que entendi a sua dúvida. Para explicar essa parte eu vou fazer mensões para as imagens que eu postei no meu comentário anterior para não repetir a bagunça que fiz no post anterior.

Pelo que eu pude entender, a sua dúvida é como o limite inferior está sendo definido e funcionando se a condição exigida é que o valor de yBolinha seja menor do que yRaquete + alturaRaquete, sendo que o mesmo quando yBolinha é maior, o código ainda funciona.

Vou explicar algumas regras por partes aqui: Primeiro: o y desse plano cartesiano cresce para baixo (quanto mais para baixo na tela, maior o valor), ou seja, quando mais para cima a posição, menor o valor. Segundo: yRaquete + alturaRaquete se refere a borda inferior da raquete.

Levando em conta a primeira regra, as posições com os menores valores de y sempre vão estar em cima na hora que foi desenhado no grafico. Na segunda imágem que eu mandei na resposta passada fica ilustrado que o código vai pegar o ponto de maior valor da raquete como limite inferior (pois os maiores valores sempre aparecem mais em baixo nesse plano) e vai considerar que Tudo que for menor do que esse ponto irá ativar a colisão com a raquete. Os valores de yBolinha maiores que isso estão fora desse limite, pois se yBolinha for maior que yRaquete+alturaRaquete, a bolinha irá passar por baixo do limite inferior. A colisão COM A RAQUETE só será ativada quando o yBolinha for menor que o valor do limite inferior. É isso que o código determina e é por isso que a colisão com a borda funciona no cenário que você postou, pois um y maior irá passar por baixo e não irá ativar a colisão com a raquete.

Sempre levando em consideração que os maiores valores de y aparecem em baixo e os menores valores de y aparecem em cima, as bordas são determinadas da seguinte forma:

Borda inferior: qualquer valor menor do que o valor da borda inferior (aparecendo em cima) irá ativar a colisão com a raquete (segunda imágem) Borda superior: qualquer valor maior do que o valor da borda superior (aparecendo em baixo) irá ativar a colisão com a raquete (terceira imágem)

Como o código usa um "and" então as duas condições devem ser obedecidas para que o código seja ativado, assim, a colisão com a raquete só acontece na interseção de valores que estão entre os valores da borda superior e da burda inferior (quarta imágem).

Espero que sua dúvida tenha sido esclarecida.

Olá, Ighor.

Começo já agradecendo pela sua útlima resposta. Muito obrigado mesmo!

Fiz algumas interações aqui com o código pra ver se o que você explicou se aplicava na prática e parece que esbarrei com outra coisa aparentemente sem sentido...

Dessa vez usei os valores normais do código:

yBolinha = 200 // raio = 7,5 // yRaquete = 150 // raqueteAltura = 240

Fazendo os cálculos teremos que yBolinha - raio é igual a 192,5 e que yRaquete + raqueteAltura é igual a 240.

De acordo com a sua explicação, tudo ocorre conforme o esperado (como mostrado na imagem abaixo) e a colisão acontece na raquete, já que 192,5 é menor que 240.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Só que essas colisões são dinâmicas. Os valores de yRaquete se alteram cada vez que nós apertamos seta pra baixo ou seta pra cima, sendo que se apertarmos seta pra baixo o valor de yRaquete será acrescido em 10 unidades e se apertarmos seta pra cima o valor de yRaquete será diminuído em 10 unidades.

Com os valores que usei e que estão explicitados mais acima, se apertarmos só seta pra baixo o valor de yRaquete + raqueteAltura sempre será maior que yBolinha - raio pois teremos sempre o valor de yRaquete sendo acrescido (com um aperto da seta pra baixo teremos yBolinha - raio igual a 250, com dois apertos teremos 260, com três teremos 270 e assim por diante), sendo assim a colisão irá acontecer com a raquete "imaginária" que está acima dela, pois a bolinha estará acima do limite inferior, conforme imagem abaixo.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Porém, usando os mesmos valores já citados, se apertamos, por exemplo, duas vezes a seta pra cima, a colisão irá acontecer com a borda da tela e não com a raquete, o que parece estranho já que o valor de yBolinha - raio não mudou, continua sendo 192,5, e o valor de yRaquete + raqueteAltura ficou como 220. 192,5 é MENOR que 220, então, pela sua explicação, a colisão deveria acontecer com a raquete, certo? Mas não foi o que aconteceu (conforme imagem abaixo)...

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Enfim, se você não quiser mais responder eu vou entender perfeitamente. Já aluguei você demais, amigo. Muito obrigado por toda a sua ajuda, de verdade!

Oi Matheus, que bom que vc ta conseguindo entender.

sobre a primeira parte (colisão com a raquete imaginária) é basicamente o que eu falei na resposta que eu postei as imágens. lá estádescrito e ilustrado o pq da colisão com a "raquete imaginária"

sobre essa segunda parte, como vc contou o quanto o yRaquete diminuiu? Pq se foi pela quantidade de toques que vc deu na ceta do teclado, eu acho que existe uma grande chance dos valores de yRaquete que vc obteve estarem errados. Eu não tenho os valores exatos, então vou apenas dar um exeplo, mas se o p5 atualiza a situação da tecla para cima no teclado em micro segundos, é impossível que vc apenas apertando a tecla para cima consiga subtrair exatamente 20 do yRaquete. Em outras palavras, o yRaquete dessa foto que vc mandou, provavelmente é menor do que o yRaquete que vc calculou utilizando esse método. Se quiser testar, coloque manualmente no código 220 como um valor para o yRaquete e veja onde na tela a raquete aparece. Provavelmente ela vai aparecer em um ponto abaixo do que nessa foto.

Espero que isso tenha ajudado.

Olá, Ighor.

Obrigado por ainda não ter desistido!

Mas sim, você perguntou como que eu contei o quanto que yRaquete diminuiu, certo? Então, esse cálculo é determinado pelo próprio código uma vez que você tem o valor inicial de yRaquete. Nós mesmos determinamos o quanto que a raquete irá se movimentar tanto pra cima quanto pra baixo na função movimentaMinhaRaquete. Segue código abaixo:

function movimentaMinhaRaquete(){
    if (keyIsDown(UP_ARROW)){
        yRaquete -= 10;
    }
    if (keyIsDown(DOWN_ARROW)){
        yRaquete += 10;
    }
}

Sobre o teste que você sugeriu, sim. Quando eu coloquei yRaquete como 220 a raquete foi mais pra baixo mesmo, mas isso já era esperado, não entendi muito bem o seu ponto com esse teste...

Enfim, eu vou botar todo o meu código atual aqui e uma imagem de como a sua execução fica na minha tela. Ele terá o valor de yRaquete como 220 como você sugeriu e algumas coisas fora do padrão como o yBolinha estar comentado na função movimentaBolinha e velocidadeXBolinha estar como -3 são coisas que estabeleci de momento para facilitar os testes. Originalmente o yBolinha na função movimentaBolinha não está comentado, velocidadeXBolinha está como 6** e **yRaquete está como 150 (ficando mais pro meio da tela)

Segue imagem abaixo e o código completo:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

//variáveis da bolinha
let xBolinha = 300;
let yBolinha = 200;
let diametro = 15;
let raio = diametro / 2;

//velocidade da bolinha
let velocidadeXBolinha = -3;
let velocidadeYBolinha = 6;

//variáveis da raquete

let xRaquete = 5;
let yRaquete = 220;
let raqueteComprimento = 10;
let raqueteAltura = 90;

function setup() {
  createCanvas(600, 400);
}

function draw() {
  background(0);
  mostraBolinha();
  movimentaBolinha();
  verificaColisaoBorda();
  mostraRaquete();
  movimentaMinhaRaquete();
  verificaColisaoRaquete();
}

function mostraBolinha(){
    circle(xBolinha, yBolinha, diametro);
}

function movimentaBolinha(){
    xBolinha += velocidadeXBolinha;
    //yBolinha += velocidadeYBolinha;
}

function verificaColisaoBorda(){
  if (xBolinha + raio > width || xBolinha - raio < 0) {
    velocidadeXBolinha *= -1;
  }

  if (yBolinha + raio > height || yBolinha - raio < 0) {
    velocidadeYBolinha *= -1;
  }
}

function mostraRaquete(){
    rect(xRaquete, yRaquete, raqueteComprimento, raqueteAltura);
}

function movimentaMinhaRaquete(){
    if (keyIsDown(UP_ARROW)){
        yRaquete -= 10;
    }
    if (keyIsDown(DOWN_ARROW)){
        yRaquete += 10;
    }
}

function verificaColisaoRaquete(){
    if (xBolinha - raio < xRaquete + raqueteComprimento
    && yBolinha - raio < yRaquete + raqueteAltura){
        velocidadeXBolinha *= -1;
    }
}
solução!

Oi Matheus, oque eu quis dizer com a resposta anterior é que quando vc apertou duas vezes a tecla para cima, vc pode ter subtraido mais do que apena 20 do valor de yRaquete. Isso aconteceu pq provavelmente o p5 executa o comando da seguinte maneira:

a cada 0,001 segundos o p5 pergunta "a tecla para cima está sendo precionada?" se a resposta for sim ele rediz 10 o yRaquete. quando vc aperta a ceta pra cima do teclado, é improvável que o seu comando dure apenas 0,001 segundo, portanto, mesmo vc apertando apenas duas vezes a tecla, provavelmente o yRaquete diminuiu mais que 20. Uma prova disso é que quando vc colocou manualmente no código yRaquete=220 a posição que a raquete apareceu foi mais baixa do que a posição da raquete quando vc fez o calculo. Um outro experimento que vc pode fazer pra ter certeza disso é utilizando o comando console.log(yRaquete) para exibir o valor de yRaquete no console em tempo real enquanto o jogo estiver sendo executado. Assim vc vai ter uma melhor noção de em quanto o yRaquete está sendo subtraído a cada toque na tecla.

Olá, Ighor.

Amigo, é com muita satifação que eu digo que você matou a charada! Você estava certo, realmete o p5 varia o valor de quanto a raquete se movimenta dependendo de quanto tempo você aperta os botões de seta pra cima e seta pra baixo! Eu não tinha prestado atenção nesse detalhe porque, acredite se quiser, eu apertava esses botões mais ou menos durante o mesmo intervalo de tempo sempre, por isso que essa diferença estava impeceptível pra mim.

Eis que entendi o que você queria com aquele teste do yRaquete como 220 e resolvi fazer um teste parecido, só que colocando yRaquete no valor padrão do meu código, que era 150.

Na imagem que eu vou mostrar mais abaixo, na primeira tela (a tela da esquerda), eu apertei duas vezes a seta pra cima como eu normalmente aperto. Na minha cabeça o valor de yRaquete depois disso deveria estar como 130. Já na tela da direita eu coloquei manualmente o valor de yRaquete como 130. Como pode ver a diferença é gritante. De fato o valor de yRaquete não estava sendo alterado na mesma quantidade quando estava apertando os botões, esse teste mostrou isso. Isso prova por A + B que você tinha razão.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Antes de marcar a sua última resposta como solução eu quis postar esse último comentário pra te dar uma satisfação de que eu finalmente entendi essa questão e como forma de agradecer também. Muito obrigado por toda a sua ajuda e por toda a sua paciência também! Você me ajudou demais. Muito obrigado mesmo, de coração!

Tudo certo, fico feliz de ter ajudado. um abraço e tudo de bom pra vc.