Una vez tenemos un protagonista capaz de moverse, el siguiente paso es crear unos enemigos dignos de nosotros: las burbujas. Empezaremos añadiendo una burbuja a nuestro juego, luego le daremos movimiento, y por fin interactividad: será capaz de acabar con nuestro protagonista. ¡Vamos a por ello!
Creando una nueva escena para las burbujas
Lo primero que vamos a hacer es crear una nueva escena llamada “Ball.tscn”. Esta escena va a ser muy similar a la de “Player”, vamos a hacer que el nodo raíz sea un KinematicBody2D
, y vamos a crearle dos nodos hijos, un CollisionShape2D
y un TextureRect
.
En el TextureRect
tenemos poco que hacer. Simplemente pon la imagen “resources/images/bubble_red.png” como Texture
.
El CollisionShape2D
tampoco nos va a dar muchos problemas. Elige en su propiedad Shape
un nuevo CircleShape2D
. Pincha sobre ese CircleShape2D
para expandir sus propiedades, y ponle como Radius
115, y en la propiedad Transform
pon position.x
y position.y
a 128, de forma que tanto la posición como el tamaño encajen con la imagen.
Ahora, para poder ver nuestra nueva burbuja, ve a la escena “Play”, dale al botón derecho sobre el nodo raíz, selecciona “Instance child scene”, y elige la escena “Ball.tscn”. Si ejecutas ahora el juego verás una burbuja flotando en el aire.
Haciendo que la burbuja se mueva
Ahora vamos a darle vida. Crea un script “Ball.gd” asociado a la escena “Ball.tscn”.
Nuestra primera idea para hacer que la burbuja se mueva sería darle una velocidad constante, igual que hicimos con “Player”. Sin embargo, lo que queremos es simular una especie de gravedad, y eso significa una aceleración. La burbuja empezará alto, debe caer cada vez más rápido, rebotar contra el suelo, empezar a subir, ir perdiendo velocidad, y en un momento dado empezar a caer de nuevo. ¿Complicado? ¡Que va!
Ya que vamos a usar una especie de gravedad, vamos a crear una constante llamada GRAVITY. Y al igual que con el protagonista, también vamos a crear un vector de movimiento.
1 | const GRAVITY = 10 |
Ahora vamos a hacer que cada vez que Godot procese las físicas del juego, se actualice la posición y la velocidad de la burbuja. La gravedad siempre hace un efecto hacia abajo, así que no nos importa si la burbuja está subiendo (motion.y negativa) o bajando (motion.y positiva). En cualquier caso vamos a sumarle el efecto de la gravedad en el delta de tiempo que ha pasado, y hacer que se mueva.
1 | func _physics_process(delta): |
Si recuerdas, en “Player” usabamos la función “move_and_slide” para hacer que se moviese. Ahora vamos a usar “move_and_collide” porque, además de moverse, esa función nos devuelve información sobre los objetos con los que la burbuja choca.
Si ejecutas ahora el código, verás que la burbuja cae al suelo y se queda parada. Necesitamos hacer que rebote.
Para hacer un rebote simple, vamos a detectar cuando el objeto que toca es el suelo, y cambiar su “motion.y”. En nuestro caso, con el valor que hemos puesto a la gravedad y la altura a la que queremos que lleguen las burbujas, un poco de prueba y error nos ha dado el valor -14. Pero te animamos a jugar con los valores de GRAVITY y BOUNCE_VEL y ver sus efectos.
1 | const BOUNCE_VEL = -14 |
Si ejecutas ahora, verás como la burbuja rebota sin parar.
Integración entre escenas: Haciendo que la burbuja sea peligrosa
Aunque tengamos un protagonista que se puede mover, y una burbuja que rebota, si pruebas a meter al protagonista debajo de la burbuja… No pasará nada. Simplemente la burbuja se detiene, ya que no puede seguir avanzando.
Tenemos que empezar a implementar algunas reglas de juego.
Lo primero es definir qué queremos conseguir. Como primera interacción, lo que queremos es que si la burbuja toca al protagonista pasen dos cosas:
- La burbuja se quedará detenida en el aire
- El protagonista mostrará la animación de “muerto”, y ya no se podrá mover más.
¡Manos a la obra!
Detectando la colisión entre la burbuja y el protagonista
Esto lo tenemos prácticamente hecho. La burbuja ya es capaz de detectar colisiones, e incluso discriminar cuando ha chocado con el suelo. Para detectar cuando ha chocado con el protagonista simplemente debemos añadir una nueva comprobación:
1 | func _physics_process(delta): |
Comunicación entre escenas: Señales
Aunque por supuesto existen muchas formas de organizar el código de un juego, a nosotros nos gusta tener un sitio central que controle las reglas comunes a diferentes escenas. Está muy bien que la burbuja sepa rebotar, y el protagonista sepa moverse, pero qué hacer cuando chocan vamos a gestionarlo en la escena “Play”.
Pero claro, para poder gestionarlo ahí, necesitamos que “Play” reciba información. ¿Y cómo se logra eso en Godot? Mediante señales.
Una señal es simplemente algo que un elemento emite, y otro elemento puede escuchar. Así que vamos a definir una señal, “Ball” va a emitirla cuando detecte una colisión con el protagonista, y “Play” la va a escuchar.
Emitiendo la señal
Para decirle a Godot que “Ball” va a emitir una señal, basta con definirla en su código con el nombre que queramos:
1 | signal player_hit_signal |
Y emitirla es muy sencillo. Se hace con la función emit_signal
. Por lo tanto, para emitir nuestra señal en la colisión el código quedaría así:
1 | func _physics_process(delta): |
Recibiendo la señal
Recibir la señal también es sencillo hay que usar la función connect
que tienen todos los nodos de Godot para conectar esa señal con una función, que se ejecutará al recibirla. Por lo tanto, crea un fichero de código “Play.gd” asociado a la escena “Play”, y añade este código a la función “_ready”:
1 | func _ready(): |
A continuación crea la función “player_hit” que se ejecutará al recibir la señal.
1 | func player_hit(): |
Si lanzas el juego, verás que cuando la burbuja toca al protagonista, en el output aparece (un montón de veces) el texto “Play: player hit”.
Crónica de una muerte anunciada
Una vez que recibimos la señal, ya podemos hacer algo con ella. Primero vamos a modificar un poco el código de “Ball” para poder hacer que se quede quieta. Simplemente vamos a añadirle una variable “paused”, y solo moverla mientras esa variable sea falsa.
1 | var paused = false |
De hecho, vamos a hacer exactamente lo mismo en “Player”. Ahí, además, vamos a comenzar la animación para la muerte del personaje que creamos el otro día (“adventure_guy_dead”).
1 | var paused = false |
Pues ya solo nos falta modificar el código de “Play” para llamar a las dos funciones que acabamos de crear:
1 | func player_hit(): |
Ejecuta el juego para probarlo, pero ¡con cuidado! Ahora si la burbuja toca al protagonista… ¡morirá!
Haciendo la burbuja aún más peligrosa
La verdad es que una burbuja botando en un sitio no da mucho miedo… Vamos a modificar un poco su comportamiento para que sea un poco más interesante. Vamos a hacer que se mueva también horizontalmente.
Que empiece a moverse de forma horizontal es muy sencillo. Simplemente, cambia la inicialización del vector de movimiento para que se mueva en el eje x.
1 | var motion = Vector2(5, 0) |
Lo que pasa es que así la burbuja se moverá siempre a la derecha, hasta salirse de la pantalla. Para no complicarnos la vida, vamos a hacer entonces una comprobación muy simple: si la posición de la bola hace que se vaya a salir de la pantalla por la izquierda o por la derecha, invertimos el valor de la coordenada x del vector de movimiento.
La función “_physics_process” de “Ball” quedará por tanto:
1 | func _physics_process(delta): |
¡Ahora sí! ¡Ya tenemos un juego de “esquivar una bola gigante” funcionando!
¡Continuará! Cada semana, un nuevo post tutorial.
Tutorial:
- Primera parte: Patapang, un tutorial para crear tu primer videojuego con Godot
- Segunda parte: Primeros pasos con Godot
- Tercera parte: Construyendo nuestro menú principal del videojuego con Godot
- Cuarta parte: Empezamos a jugar
- Quinta parte: Animando al protagonista
- Sexta parte: Esquivando burbujas
- Séptima parte: Rompiendo burbujas