Detección de colisión de la bola en la pala

Para determinar si la bola ha colisionado con la pala podríamos usar varias sentencias if preguntando si la posición X de la bola corresponde con aquella en la que esté contactando con el lado izquierdo de la pala, y si su posición Y se encuentra entre los lados superior e inferior de la pala, pero habría que tener en cuenta también que el centro de la bola puede estar por debajo del borde inferior de la pala, pero que contacten por el lado de la bola. Así que el número de preguntas que hay que realizar puede ser algo elevado.

Método intersect de la clase Shape

Una manera más sencilla, y que te puede ser útil de conocer para otros juegos que quieras desarrollar, es utilizar el método intersect que ofrece la clase Shape. Este método permite obtener una nueva forma geométrica formada por la intersección de dos formas geométricas que se indiquen como parámetros. Quizá puedas verlo más claro en la imagen de ejemplo que ofrece la API de este método:

Screen Shot 2018 01 15 at 21.03.00 a9a36

Como puedes ver, la intersección de dos formas geométricas está formada por las zonas comunes a ambas figuras.

Esto podemos utilizarlo para detectar las colisiones de dos formas geométricas como son las pala y la bola. Si la forma resultante de la intersección de la pala y la bola está vacía significará que NO están en contacto.

La forma de invocar a este método es algo diferente a la manera que hemos utilizado con otros métodos en este tutorial. Aunque es algo sencillo, como verás al final, conviene que conozcas más en profundidad algunos detalles de este método, ya que son cuestiones que te encontrarás en más ocasiones.

Métodos de tipo static

Hasta ahora, las llamadas a un método se han hecho colocando delante (precedido por un punto) un objeto correspondiente a la clase a la que pertenece el método. Es decir, cuando hemos coloreado el rectángulo de la pala hemos usado la siguiente llamada: 

rectStick.setFill(Color.WHITE);

Es decir, para llamar al método setFill de la clase Rectangle, hemos tenido que indicar previamente un objeto de la clase Rectangle. O en esta sentencia que permitía cambiar el título de la ventana:

primaryStage.setTitle("PongFX");

Se utiliza el método setTitle, que es de la clase Stage, poniendo delante un objeto de la clase Stage.

Siempre es importante observar la manera en la que está declarado cada método que vamos a emplear. En la API del método intersect podemos ver que está declarado de la siguiente manera:

Screen Shot 2018 01 15 at 21.09.04 00987

En los paréntesis podemos ver que se le deben pasar 2 objetos Shape como parámetros (Shape shape1, Shape shape2). Es decir, en nuestro caso se pasará por parámetro el objeto Shape de la bola (Circle) y el objeto Shape de la pala (Rectangle). Recuerda que las clases Circle, Rectangle y las de otras formas geométricas son subclases de la clase Shape, como se indica en la API de la clase Shape.

Screen Shot 2018 01 15 at 21 05593

También vemos en la parte izquierda de la declaración del método intersect que aparece la palabra static.

Screen Shot 2018 01 15 at 21 37cd5

Los métodos declarados como estáticos (static) en Java deben ser invocados utilizando el nombre de la clase en lugar de un objeto.

Es decir, la llamada a este método se debe hacer como:

Shape.intersect(circleBall, rectStick);

Normamente se declara un método como estático cuando su ejecución no se aplica sobre un objeto concreto, como es este caso. La intersección no se aplica sobre un sólo objeto. En cambio, en los ejemplos que hemos visto anteriormente de método que no son estáticos, el resultado afectaba a objetos concretos, por ejemplo, al cambiar el color de la pala.

Tipo de dato de retorno de los métodos

Vamos a fijarnos también en la palabra Shape que aparece justo a la izquierda del nombre del método en la documentación. En esa posición se indicará siempre el tipo de dato que va a retornar la llamada al método.

Screen Shot 2018 01 15 at 21 06503

Ten en cuenta que esta información también aparece cuando se despliega la lista desplegable de métodos disponibles para un objeto o para una clase desde NetBeans, pero desde este entorno de desarrollo el tipo de dato retornado aparece en este caso en la parte derecha. De todas formas, recuerda que NetBeans también te muestra la documentación completa de la API en la ventana emergente inferior, como puedes ver también en la siguiente imagen:

Screen Shot 2018 01 15 at 21 3cad2

También es importante saber que en el texto de la documentación se explica qué representa el objeto retornado (donde dice Returns ...). En este caso, como ya se había dicho, retorna la forma geométrica resultante de la intersección de las 2 formas geométricas pasadas por parámetro.

Esa forma retornada la podemos guardar en una variable para seguir usándola posteriormente. Escribe estas sentencias dentro del método handle de AnimationTimer, ya que se debe estar comprobando contínuamente si hay una colisión.

Screen Shot 2018 01 15 at 22.07.50 a7403

Nuestro interés está en conocer si la forma resultante de la intersección está vacía o no. Sin que nos compliquemos ya mucho en entender detenidamente los métodos a usar para ello, podemos obtener esa información con la siguiente sentencia (bounds son los bordes de la forma geométrica):

Screen Shot 2018 01 15 at 23.05.09 7c0e5

En este caso, como puedes observar, el método isEmpty que es llamado al final de la sentencia retorna un valor de tipo boolean, que aprovechamos para guardar en la variable colisionVacia. Esa variable almanacenará el valor true (verdadero) si la forma resultante de la colisión está vacía (es decir, no hay colisión), o false (falso) si se ha obtenido algo como resultado de la intersección (hay una colisión).

El tipo de dato boolean de Java permite hacer referencia a dos únicos valores: verdadero (true) y falso (false).

Por tanto, si comprobamos si esa variable contiene el valor false, querrá decir que se ha producido una colisión de la bola con la pala. En ese caso, lo que hay que hacer es cambiar la direccion de la bola, para que la coordenada X de su posición se vaya decrementando moviéndose así hacia la izquierda de la ventana:

Screen Shot 2018 01 15 at 23.13.25 77399

Ejecuta la aplicación y comprueba que la bola ya rebota en la pala.