Creación de Videojuegos. Godot Engine. Checkpoints

Tema 17. Godot Engine. Checkpoints

Recordemos hasta ahora, si el jugador cae en un agujero, la escena se reinicia. Pero siempre se reinicia desde el principio. ¿Qué ocurre si deseamos que el jugador no empiece otra vez la escena, sino que se restablezca su posición a partir de  donde se ha quedado?

Para poder dar una solución a este problema, también emplearemos áreas2D

Para ello creamos una nueva Área2D con su CollisionShape2D. La llamaremos CheckArea2D0

Creamos una nueva Área2D con su CollisionShape2D. Godot
Creamos una nueva Área2D con su CollisionShape2D. Godot

Pero ahora guardaremos dicha área como si fuera una escena. Nos ponemos encima del Nodo CheckArea2D0 y guardamos como Guardar Rama como Escena, lo cual nos permite guardar dicho Nodo como si de una escena se tratara.

Guardar Rama como Escena. Godot
Guardar Rama como Escena. Godot

Si nos fijamos en los recursos, veremos que el Nodo se ha guardado como una Escena (CheckArea2D0.tscn)

El Nodo se ha guardado como una Escena (CheckArea2D0.tscn). Godot
El Nodo se ha guardado como una Escena (CheckArea2D0.tscn). Godot

Si nos fijamos, el CheckArea2D es tratado como una escena. Vemos el icono escena.

El CheckArea2D es tratado como una escena. Godot
El CheckArea2D es tratado como una escena. Godot

El área CheckArea2D la situamos delante del Player.

Situamos el área CheckArea2D delante del Player. Godot
Situamos el área CheckArea2D delante del Player. Godot

Ahora conectamos el CheckArea2D con el Player, igual que lo hicimos con las áreas anteriores.

func _on_CheckArea2D0_body_entered(body):
pass # Replace with function body.

Y procedemos a duplicar el área. Pero esta vez es importante que conectemos de forma manual la nueva área o áreas que dupliquemos con la misma área inicial:

Es decir:

  1. Duplicamos el área CheckArea2D0
  2. Conectamos el CheckÁrea2D0 con el Player.
  3. Duplicamos el CheckArea2D y obtendremos CheckArea2D1
  4. OJO: Conectamos el CheckArea2D1 con el CheckArea2D0:

Importante:

Al duplicar nos aparecerá el área _on_CheckArea2D1_body_entered… nosotros la renombraremos por _on_CheckArea2D0_body_entered:

Renombraremos el área _on_CheckArea2D1_body_entered por _on_CheckArea2D0_body_entered. Godot
Renombraremos el área _on_CheckArea2D1_body_entered por _on_CheckArea2D0_body_entered. Godot

y le damos al botón Conectar. Ahora ya tenemos conectado el CheckArea2D1 con la misma función que CheckArea2D0.

Lo que hemos hecho es que ambas áreas usen la misma función:

Tenemos conectado el CheckArea2D1 con la misma función que CheckArea2D0. Godot
Tenemos conectado el CheckArea2D1 con la misma función que CheckArea2D0. Godot
func _on_CheckArea2D0_body_entered(body):
pass # Replace with function body.
Escena con los checkpoints (Áreas2D). Godot
Escena con los checkpoints (Áreas2D). Godot

Ahora vamos a definir una nueva CheckArea2D y haremos los mismos pasos:

Añadimos una nueva Área2D. Godot
Añadimos una nueva Área2D. Godot
PUNTO DE GUARDADO

Lo que haremos ahora será programar un punto de guardado. Haremos un CheckPoint cada vez que el jugador esté en cualquiera de esas áreas.

En Godot podemos obtener la posición global de un objeto accediendo al body desde la función 

func _on_CheckArea2D0_body_entered(body):

pass # Replace with function body.

usando body.global_position

es decir:

func _on_CheckArea2D0_body_entered(body):
print(body.global_position)

Cada vez que el Player toque un CheckArea2D, obtendremos su posición en la pantalla:

Salida por consola de la posición del Player. Godot
Salida por consola de la posición del Player. Godot

Para asegurarnos que es el Player el que toca los CheckAreas, añadimos la condición

func _on_CheckArea2D0_body_entered(body):
if body == self:
print(body.global_position)

Ahora ya conocemos la posición del jugador cuando toca un área. Entonces necesitaremos guardar esta información cuando el jugador caiga.

Por lo tanto tenemos que guardar dicha información independientemente de las veces que la escena se reinicie.

Por lo tanto vamos al área de recursos y creamos un Script. Antes crearemos una carpeta donde almacenaremos todos los scripts. 

Creamos una carpeta Scripts en el área de recursos:

Creamos la carpeta Scripts en recursos. Godot
Creamos la carpeta Scripts en recursos. Godot

Y dentro creamos un nuevo Script con el nombre: DataManager

Creamos el Script DataManager.gd dentro de la carpeta Scripts. Godot
Creamos el Script DataManager.gd dentro de la carpeta Scripts. Godot

Nota: si tenemos otros Scripts los podemos arrastrar todos dentro de dicha carpeta para tenerlo todos mejor organizados.

En el Script hacemos los siguiente:

Creamos una variable para guardar la posición del personaje:

Ahora en Configuración del Proyecto tenemos que definir el Script como AutoLoad

En Configuración del Proyecto definimos el Script como AutoLoad. Godot
En Configuración del Proyecto definimos el Script como AutoLoad. Godot

Y hay que darle la ubicación del Script desde la carpeta Ruta. Seleccionamos el Script DataManager.gd

Seleccionamos el Script DataManager.gd. Godot
Seleccionamos el Script DataManager.gd. Godot

y botón Añadir (no olvidarse)

Pulsamos el botón Añadir. Godot
Pulsamos el botón Añadir. Godot

Una vez hecho esto podemos usar el AutoLoad desde cualquier Script:

Para hacer esto solo es necesario llamarlo por su nombre desde cualquier Script:

func _on_CheckArea2D0_body_entered(body):
if body == self:
DataManager.init_position = body.global_position

Mediante este código, guardamos la posición del Player según el CheckArea que haya tocado. Y se guarda en la variable del Script AutoLoad que hemos definido.

Para recuperar la posición guardada la mejor forma de hacerlo es en la función func _ready():

que se ejecuta cada vez antes de que se inicie una escena.

Por lo tanto ahora recuperamos la última posición del Player (que es la última CheckArea2D que ha tocado) de tal forma que cuando caiga y vuelva a reiniciarse la escena, lo hará en la posición devuelta en la función ready:

func _ready():
global_position = DataManager.init_position

La principal función de los AutoLoads es la de compartir información entre las escenas.

Nuestro código quedará así:

extends KinematicBody2D


# Declare member variables here. Examples:
# var a = 2
# var b = “text”
export var Velocidad = 200
var velo = Vector2()

# Called when the node enters the scene tree for the first time.
func _ready():
global_position = DataManager.init_position

# Called every frame. ‘delta’ is the elapsed time since the previous frame.
func _process(delta):
velo.y += Velocidad * delta
if Input.is_action_pressed(“Jump”) and is_on_floor():
velo.y = -Velocidad
if Input.is_action_pressed(“Player_Left”):
$AnimationPlayer.play(“Left”)
velo.x = -Velocidad
if Input.is_action_pressed(“Player_Right”):
$AnimationPlayer.play(“Right”)
velo.x = Velocidad
if !Input.is_action_pressed(“Player_Left”) and !Input.is_action_pressed(“Player_Right”):
$AnimationPlayer.play(“Idle”)
velo.x = 0
if !is_on_floor():
$AnimationPlayer.play(“Animacion_JUMP”) #Personaje saltando
move_and_slide(velo,Vector2(0,-1))


func _on_Area2D_body_entered(body):
if body == self:
get_tree().reload_current_scene()


func _on_CheckArea2D0_body_entered(body):
if body == self:
DataManager.init_position = body.global_position
El personaje aparece en el mismo punto del último checkArea tocado después de caer.
El personaje aparece en el mismo punto del último checkArea tocado después de caer.
PUNTO DE INICIO EN EL JUEGO

Si nos fijamos cuando el Jugador inicia la escena después de caer, este cae desde arriba debido a que las coordenadas iniciales son la 0,0 

Podemos solucionar esto modificando el Script AutoLoad DataManager

 así: 

Ajustamos por defecto las coordenadas de inicio del personaje en el juego cada vez que entre en escena:

extends Node

var init_position = Vector2(-75,200)

Ahora podemos mejorar los tamaños de cada CheckPoint e insertar Tiles encima para indicar al jugador mediante gráficos si creemos oportuno. Por ejemplo un reloj o cualquier objeto que indique que continua a partir de ahí.


ÍNDICE


0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x