Física

Pilas incluye integración con un sistema de física para realizar simulaciones y dotar a tus juegos de mas realismo y diversión.

El motor: Box2D

El motor de física seleccionado para pilas se llama Box2D, el mismo motor de física utilizado en el juego Angry Birds.

Así, Box2D y PyBox2D son las bibliotecas protagonistas de casi toda la funcionalidad que vas a ver en este módulo.

El módulo pilas.fisica es solamente un facilitador para utilizar Box2D, y que puedas comenzar a jugar con físicas rápidamente.

Así que aprovecho este espacio para dar las gracias a Erin Catto, y su grupo de desarrollo por haber creado Box2D.

Unos ejemplos

El motor de física se puede mostrar en funcionamiento usando un ejemplo, escribe el siguiente código:

pelotas = pilas.actores.Pelota() * 10

esto creará un grupo de circunferencias que rebotarán hasta la parte inferior de la pantalla.

De manera similar puedes crear un montón de cajas y hacerlas rebotar:

cajas = pilas.actores.Caja() * 10

Como puedes ver, el resultado es un grupo caótico de actores chocando entre sí. Mas adelante veremos como personalizar y "controlar" un poco el escenario.

Los actores que tienen física son un poco particulares, pero aún así se los puede tratar como a otros actores. Por ejemplo, si quieres poder arrastrar y soltar figuras con el mouse, puedes enseñarles una habilidad:

pelotas.aprender("arrastrable")
cajas.aprender("arrastrable")

Modo depuración de física

Cuando haces juegos con física o movimientos realistas es muy importante tener en cuenta un concepto importate:

Si bien uno observa pelotas y cajas, en realidad, internamente son solo cuadrados y circunferencias.

Lo que ocurre en pantalla son dos cosas, por una lado vemos imágenes con aspecto de caja o pelota, y por el otro se nos oculta una simulación entre polígonos mucho mas primitiva y simple.

Observa esta escena:

Cada uno de esos actores está asociado a una figura geométrica, la física en realidad se da en un nivel muy primitivo de figuras. El aspecto de las cosas es solo eso, un aspecto. Lo que "manda" en el comportamiento físico son las figuras geométricas (cuerpos).

Intenta lo siguiente, pulsa la tecla F11 o pulsá el botón "mostrar figuras físicas" que aparece abajo a la derecha:

Las lineas blancas indican polígonos que el motor de física puede controlar, las cajas tienen forma rectangular, los actores Pelota tienen figuras circulares, y el suelo y las paredes también están en el sistema de física.

Si por algún motivo quieres que los objetos no estén contenidos en la pantalla, y sean un poco mas libres, podrías eliminar las paredes:

pilas.fisica.eliminar_paredes()

o incluso podrías eliminar el suelo:

pilas.fisica.eliminar_suelo()

Pero recuerda que los objetos que no se ven en la pantalla de todas maneras estarán ahí. Una buena idea es eliminarlos ni bien los dejas de usar.

Física personalizada

Los actores Pelota y Caja están bien para simulaciones simples y generales. Pero, ¿cómo podemos dotar a nuestros propios actores de ese comportamiento?.

Los objetos o figuras físicas viven dentro del módulo de física y son invisibles (al principio), pero luego se pueden vincular a cualquier actor con facilidad.

Intenta lo siguiente, ingresa en el modo interactivo de pilas y pulsa la tecla F11 o pulsá el botón "mostrar figuras físicas" que aparece abajo a la derecha:

Ahora creá dos figuras físicas, una circunferencia estática y otra dinámica:

circulo = pilas.fisica.Circulo(0, 0, 50, dinamica=False)
circulo_dinamico = pilas.fisica.Circulo(10, 200, 50)

El primer círculo aparecerá en el centro de la ventana, y el segundo comenzará en la posición (10, 200), es decir, en la parte superior de la ventana y luego caerá rebotando. Algo así:

Ahora bien, habrás notado que estas dos circunferencias las podemos ver porque está habilitado el módulo de depuración (que activamos con F11), pero esto no lo va a ver alguien que juegue a nuestro juego. El modo depuración es solo para desarrolladores.

Lo que nos falta hacer, es darles apariencia a esas figuras. Algo así como una piel..

Para esto podemos usar actores. La dinámica es así, tenemos que crear dos actores, y luego decirle a estos actores que se comporten cómo figuras geométricas.

Agreguemos a nuestro programa estas 4 lineas de código, queremos que el primer circulo (el del centro) sea un mono, y el otro círculo que sea una bomba:

mono = pilas.actores.Mono()
mono.aprender(pilas.habilidades.Imitar, circulo)

bomba = pilas.actores.Bomba()
bomba.aprender(pilas.habilidades.Imitar, circulo_dinamico)

Esto es diferente a lo anterior, los objetos físicos ahora tienen apariencia:

Ahora podríamos desactivar el modo depuración física (pulsando nuevamente F11) y jugar un poco impulsando la bomba de un lado a otro:

circulo_dinamico.y = 200

Ten en cuenta que ahora la figura del motor físico es la que determina el movimiento y la rotación, así que ya no funcionará escribir algo cómo bomba.y = 200, ahora tienes que escribir circulo_dinamico.y = 200 para mover al actor...

Otra cosa a considerar, es que en nuestro ejemplo no ajustamos muy bien el tamaño del circulo_dinamico con el de la bomba. Esto es un detalle poco relevante aquí, porque solo quiero explicar cómo se usa el motor, pero cuando hagas tus juegos, recuerda usar el modo depuración de física para detectar estos detalles y corregirlos, son muy importantes para que tus usuarios disfruten del juego. Recuerda que ellos no verán los círculos rojos... solo verán la apariencia de los actores.

Escala real y tamaño de figuras

Pilas utiliza una pantalla que se puede medir en pixels, de hecho, todas las imágenes tienen un tamaño en pixels predefinido.

Pero dentro del mundo físico de box2d, las figuras no tienen tamaño en pixels sino en metros.

¿Cual es la relación?, pilas convierte pixels a metros para mantener al mundo de box2D en coherencia con lo que estamos viendo en pantalla.

30 pixels son equivalentes a 1 metro:

Cambiando la gravedad interactivamente

Por defecto, la gravedad del escenario es de (0, -9), esto significa que los objetos se dirigen hacia abajo, y lo hacen con una aceleración de 90 mts/s^2 (metros sobre segundos cuadrados).

Pero no estás obligado a que esto sea siempre así, de hecho si quieres hacer un juego que transcurra en el espacio seguramente vas a querer eliminar por completo la gravedad del escenario para que los objetos puedan "flotar", ¿no?.

Entonces, Podrías cambiar la gravedad en cualquier momento cambiando los atributos gravedad_x o gravedad_y del objeto fisica así:

pilas.fisica.gravedad_x = 20
pilas.fisica.gravedad_y = 0

El atributo gravedad_x representará la aceleración horizontal, donde los valores positivos acelerán los objetos hacia la derecha, y los valores negativos a la izquierda.

De forma similar funciona el atributo gravedad_y, los valores positivos aceleran los objetos hacia arriba y los valores negativos hacia abajo.