jueves, 7 de noviembre de 2019

Introducción al RigidBody2D

ADVERTENCIA: El tutorial de este artículo fue traducido de kidscancode.org. Sin embargo la traducción está basada en mi experiencia con el inglés, así que no flipéis con la super traducción :)

RigidBody2D


Este es uno de los nodos que más confusión y dolor de cabeza nos trae a nosotros los estudiantes. Recuerdo que cuando estaba aprendiendo Unity quise hacer un personaje estilo arcade para un plataformas clásico pero estaba usando un RigidBody en lugar de un kinematicBody (esto más por desconocimiento que por otra cosa), recuerdo que me causó un trauma psicológico porque por más que lo intentaba no me lograban salir los movimientos y el comportamiento que quería, fue tanta la frustración que abandoné Unity y me dediqué a buscar otro motor (no conocía Godot).

Ahora con Godot me siento tan familiarizado y tan contento tanto con el motor como con el editor que el trauma se me está pasando poco a poco,  y ahora he abierto mi mente para aprender el comportamiento de los nodos de tipo RigidBody2D.


En este tutorial, te explicaré cuando usar (y cuando NO usar) un RigidBody2D, aprenderás como funcionan, y también verás algunos trucos sencillos para que puedas aplicarlos. Esto también aplica para los RigidBody en 3D.

Introducción

El RigidBody2D es un cuerpo físico de Godot que provee física simulada. Esto quiere decir que tu no puedes controlar un RigidBody2D directamente. En su lugar le debes aplicar fuerza (gravedad, impulso, etc.) y el motor de físicas de Godot calculará el movimiento resultante, incluyendo colisiones, rebotes, rotaciones, etc.
Puedes modificar el comportamiento de un RigidBody2D a través de sus propiedades en el inspector tales como  “Masa”, “Fricción”, o “Rebote”:



El comportamiento del RigidBody2D también se puede alterar en las configuraciones del proyecto (Project Settings >> Physics >> 2D)

Usando un RigidBody2D

Uno de los grandes beneficios que se obtienen al usar un RigidBody2D es que muchas de las implementaciones de código para simular sus movimientos y colisiones ya los podemos conseguir de forma gratuita y sin tirar ni una línea de código. Por ejemplo, vamos a crear una mecánica sencilla al estilo “Angry Birds” con bloques cayendo al piso como consecuencia de un golpe al costado por una bola. Solo necesitas crear un RigidBody2D para la escena del bloque y luego duplicarlo para armar una pila, luego armas otra escena que haga de bola para que los golpee. El apilamiento de las cajas, las caídas y los rebotes, serán calculados automáticamente por el motor de físicas.

Apilando los bloques

Comienza creando una escena y agregando un nodo RigidBody2D, también agrega un sprite y un CollisionShape2D como hijos del RigidBody2D. 


Agrega una textura al sprite y una forma rectangular al CollisionShape. 
IMPORTANTE: No cambies la escala del CollisionShape! Es una mala idea y resultará en comportamientos inesperados y difíciles de debuguear. Siempre usa los puntos internos que manejan el tamaño del nodo.
NOTA: Para las texturas de este ejemplo estoy usando el paquete de  Assets del sitio Kenney.nl. Te recomiendo esta página ya que contiene una amplia variedad de bloques en diferentes figuras, materiales y formas.
Pulsa F6 para reproducir la escena y verás el bloque caer poco a poco hasta que desaparece. Esto es debido a la gravedad. Puedes configurarla en los ajustes del proyecto “Project Settings” en la sección Physics -> 2d. También puedes cambiar la escala de gravedad del bloque a través de su propiedad Gravity Scale en el Inspector. Yo estoy usando una escala con un valor de 3.
Ahora crea una escena principal (Normalmente uso un Node2D) y agrega un nodo StaticBody2D con un CollisionShape rectangular que servirán de "suelo" y "paredes".
Instancia la escena Bloque, y luego duplícala con (Ctrl-D) para que puedas crear una pila de bloques. 
Algo como esto:

Creando el Proyectil

Crea otra escena con las mismas configuraciones del nodo Bloque pero llámala "Ball". Usa una de las texturas redondas y una figura de colisión circular. Instánciala en tu escena principal y colócala en algún lugar de la pantalla que esté alejado de la pila de bloques.
Para hacer que el RigidBody2D se mueva, este debe tener una velocidad. Puedes darle una velocidad inicial usando la propiedad Linear -> Velocity. Ajústala a (500,0).

También puedes jugar con la propiedad Friction de la bola y con la propiedad Bounce (rebote). Ambas propiedades pueden ser ajustadas en un rango de 0 a 1. A mi me gusta ajustar el Bounce a 0.5.
IMPORTANTE: NUNCA escales un cuerpo físico (RigidBody2D, StaticBody2D, Area2D, KinematicBody2D). Si lo haces entonces una advertencia aparecerá y cuando la escena se ejecute, el motor de físicas automáticamente ajustará su escala nuevamente a (1, 1).

Fuerzas Físicas

Resetea la propiedad Linear Velocity a (0, 0). Ahora, ¿Que pasa si lo que queremos es arrojar la bola? Nunca deberías ajustar la velocidad del Nodo manualmente, estas son simulaciones físicas del mundo real. En la vida real los objetos no saltan de un lugar a otro de repente. Si intentas esto, el motor de físicas se resistirá a hacerlo, y por lo tanto ocurrirán movimientos inesperados. En lugar de eso, debemos aplicarles fuerzas, las cuales crean aclaraciones en una cierta dirección (esto se conoce como la segunda ley de Newton). Los objetos físicos de Godot funcionan de la misma manera.
Tenemos 2 funciones disponibles a la hora de agregar fuerza a un RigidBody2D:
  • add_force()
Agrega una fuerza continua al cuerpo. Imagina esto como el empuje o la propulsión de un cohete espacial. Esta fuerza se aplica sin importar la velocidad existente del nodo, lo cual se traduce como "mientras se siga aplicando la fuerza entonces habrá mayor velocidad". La fuerza se sigue aplicando hasta que es removida.
  • apply_impulse()
Esta función agrega un impulso instantáneo al cuerpo. Imagina esto como patear una pelota de fútbol o batear una pelota de béisbol.
Usaremos la función apply_impulse() para patear la bola cuando arrastremos y soltemos el ratón.
Abre los ajustes del proyecto “Project Settings” y busca la pestaña “Input Map”, agrega una nueva acción y llámala “click”. Ahora conéctala con el mouse izquierdo del ratón.
A continuación, agrega un script a la escena Ball y agrega el siguiente código:

Este script lleva la variable dragging a true cuando el clic del ratón se presiona y guarda la posición global donde el clic fue realizado. Cuando el clic es liberado entonces calculamos la diferencia de la posición del clic inicial con la final, esto resulta en un vector de posición. Usamos ese vector para aplicar el impulso al cuerpo pero aumentado su escala 5 vecesapply_impulse() también recibe un parámetro offset de primero. Esto permite golpear la bola desde otro lugar que no sea el centro del cuerpo.
Si has hecho todo bien entonces deberías de poder realizar algo como esto:

Conclusión:
Los RigidBody2D con cuerpos físicos que Godot nos ofrece para poder simular entornos físicos en nuestros juegos. No los puedes mover directamente porque esto no sucede en el mundo real (a menos que tengas poderes de telequinesis), en su lugar debes aplicarles fuerzas físicas las cuales se rigen por la segunda ley de Newton.
Para agregar fuerza a un RigidBody2D puedes usar las funciones add_force() o add_impulse(). La diferencia es que  la primera agrega una fuerza constante causando que el cuerpo adquiera más y más aceleración; mientras que la segunda aplica un impulso instantáneo como si pateásemos una pelota de fútbol.

Bien, espero que con esto hayas entendido un poco sobre los nodos RigidBody2D. Hasta la próxima!