Movimiento y salto de un cuerpo

por Mar 18, 2018Godot Engine, Tutoriales11 Comentarios

Vamos a aprender sobre las funciones básicas para el movimiento de un cuerpo KinematicBody2D. Haremos que se mueva y pueda saltar en la tierra.

Puedes descargar el proyecto final desde Aquí.

Creando los nodos

Nuestro jugador es un KinematicBody2D. Sus hijos son:

  • Sprite2D (spr): encargado de guardar la imagen del jugador.
  • CollisionShape2D (col): es la mascara que define el lugar donde el cuerpo tiene colisiones.
  • Camera2D: es la cámara que centra la imagen del juego en el protagonista.

Además de eso, nuestro jugador tiene una hoja al lado de su nombre. Es un script, lo tenemos que crear para poder programar su movimiento.

Programando dentro del script

Dentro del proyecto que han descargado, van a encontrar todo el código que yo he realizado. Voy a explicarlo por partes:

Primero vamos a crear las variables.

# Contenedores de resultados fisicos para el movimiento
var distance = Vector2()
var velocity = Vector2()

# Velocidades
var speed = 140
var gravity = 650
var jump_speed = 250

Con las variables de tipo Vector2() vamos a controlar el movimiento del Kinematic en la pantalla, podemos cambiar su aceleración desde las variables que declaramos debajo. Si quieren más información sobre el movimiento que vamos a realizar, pueden buscar en internet sobre el Movimiento Rectilíneo Uniforme (M.R.U).

Ahora vamos a activar el proceso físico y dentro le ponemos nuestra función para calcular el movimiento.

func _ready():
	set_physics_process(true)

func _physics_process(delta):
	_move(delta)

La función _move no viene por defecto en Godot, es necesario que nosotros la creemos. Vamos con eso.

# Controlador de todo lo relacionado con el movimiento
func _move(delta):
	
	# Dirección del jugador según la tecla presionada
	var direction_x = int(Input.is_action_pressed("ui_right"))-int(Input.is_action_pressed("ui_left"))

Ya hemos creado la función _move (recordemos que se le tiene que pasar como parámetro el Delta, por ser el tiempo). Dentro de _move tenemos casi todo el código del tutorial, primero declaramos una variable para la dirección (direction_x).

El valor de esa variable parece difícil de entender, pero es muy  fácil: vamos a obtener el valor de las flechas «derecha» y «izquierda» cada vez que sean presionadas. Cuando usamos una función con «is_action…» vamos a tener un valor booleano, así que lo pasamos a «int»(número entero), cuando es True nos llega un 1, con False llega un 0. Si se presiona la flecha de la izquierda, se resta al 0, y si es la derecha, se suma.

Ahora vamos a aplicar un cambio en nuestra imagen.

if direction_x < 0:
		$spr.flip_h = true
	elif direction_x > 0:
		$spr.flip_h = false

Si nuestra dirección es -1, vamos a voltear la imagen de nuestro jugador. En caso contrario, la ponemos normal.

Recordemos que para voltear la imagen tenemos que entrar en el Sprite2D (spr) y alterar sus parámetros. Para entrar en un nodo hijo del jugador (o cualquier nodo), usamos el «$» con el nombre del nodo ($spr) y después de un «.» escribimos el parámetro que queremos usar.

Ahora vamos a usar las formulas físicas que se usan en el M.R.U.

# Formulas fisicas para obtener la velocidad y la gravedad
	distance.x = speed*delta
	velocity.y += gravity*delta
	velocity.x = (distance.x*direction_x)/delta

En la «velocity.x» es necesario calcular la distancia junto con la dirección, ya que la dirección se encarga de convertir el valor en negativo o positivo. Si no se usa, siempre será positivo y siempre irá a la derecha.

Para aplicar todo lo que hemos calculado ponemos:

# Aplicar el movimiento y ajustar un suelo
	move_and_slide(velocity, Vector2(0,-1))

Con eso tenemos el movimiento, calculado en nuestra variable velocity. Además, aplicamos la gravedad.

En el segundo parámetro (Vector2(0,-1)) estamos indicando que la parte de un objeto, que nosotros conocemos como «piso» es arriba.


Ahora tenemos el movimiento, sólo falta arreglar los problemas con la gravedad y aplicar el salto del jugador.

Primero tenemos que obtener una lista de las colisiones cada vez que nos movemos (todo dentro del _move()).

# Obtener las colisiones cada vez que chocamos con otro cuerpo
	var get_col = get_slide_collision(get_slide_count()-1)

Con esto vamos a tener la última colisión que se realice entre nuestro jugador con otro cuerpo. Ahora vamos con el salto:

if is_on_floor():
		velocity.y = 0
		
		if Input.is_action_just_pressed("jump"):
			velocity.y = -jump_speed

Esto es sencillo: con «is_on_floor» estamos diciendo que cada vez que estemos en el piso (lo definimos arriba), se cancele la gravedad y se ejecute lo que tengamos dentro. En nuestro caso, sólo tenemos dentro otro «if» que usamos para que al momento de presionar la tecla de espacio se aplique la velocidad de salto. Recuerden que el negativo es para arriba y el positivo para abajo, por eso la velocidad de salto es negativa… la acción «jump» no esta por defecto, si quieres aprender a crear tus propias acciones ven Aquí.

Ya hemos terminado. Si tienen una duda, déjenla en los comentarios y trataré de responderla.

Puedes complementar lo que has leído aquí con el siguiente vídeo:

[embedyt] https://www.youtube.com/watch?v=ZNa_qE58gVI[/embedyt]

¡Comenta! 👇️

11 Comentarios

  1. Jose Hernandez

    is amazing omg no me lo puedo creer es la mejor pagina web de desarrollo de videojuegos del mundo like like like

    Responder
  2. Sexedura

    I’ve been exploring for a little for any high-quality articles or weblog posts on this sort of house . Exploring in Yahoo I eventually stumbled upon this site. Reading this info So i’m happy to convey that I’ve a very good uncanny feeling I came upon exactly what I needed. I most definitely will make certain to do not omit this website and give it a glance on a relentless basis.
    Rexuiz Shooter

    Responder
    • César León

      I’m very happy that my articles you like. I hope you do not have problems with the translation, I am not very good at writing in English. I’m working with some colleagues to make the publication of the tutorials in both languages. Thank you very much for being here 🙂

      Responder
  3. Juan José

    Hola! No me queda claro el tema de la colisión contra el suelo. En este ejemplo no agregás el suelo ¿que tipo de objeto sería? ¿hay que agregarle algo más?

    ¿La CAMERA2D se le agrega al jugador para que la camara siga el movimiento?

    Responder
    • César León

      Hola, en el proyecto ya el suelo esta dentro. Generalmente se usa un nodo StaticBody2D para hacer suelos y paredes, dentro de él colocas un CollisionShape2D y el Sprite que quieres para tu bloque, como con un KinematicBody. Sí, la cámara se agrega para que se siga al jugador.

      Gracias por tu comentario, un saludo.

      Responder
  4. cmkat

    Hola podrias hacer uno para pantallas de carga?

    Responder
    • César León

      Vale, en cuanto tenga tiempo le publico. Incluso me parece que Godot tiene su propio nodo para eso, gracias por ver 🙂

      Responder
  5. marcelo

    el archivo en mega no existe

    Responder
  6. Thomas

    hola lo que pasa esque el personaje cuando mantengo presionado el de saltar no lo hace una vez, al contrario empieza a subir hasta que no suelte el boton, aparte la gravedad hace que caiga muy baja me toca ponerle numeros grandes pa que caiga de una
    hay si no que que toca hacer
    ojala respondas y me aydudes en el inconveniente

    Responder
  7. karikioX7

    Quizás te paso eso porque no pusistes el «Input.is_action_pressed(«arriba»)» debajo del «is_on_floor», si lo colocas así, solo podrás dar el salto cuando estés en el suelo y no en cualquier momento en el te encuentres.
    El problema de la gravedad que dices no se como ayudar, bueno supongo que con una gravedad de 750 estaría bien, o inclusive hasta 980 xd, eso es de ir jugando con los valores. Saludos xd

    Responder

Enviar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

¿Qué son los setters/getters en GDScript?

¿Qué son los setters/getters en GDScript?

En varios tutoriales donde hago uso de la palabra reservada "setget", dejo el enlace con la explicación de la documentación oficial sobre esa función. Sea porque en una que otra ocasión me haya olvidado de enlazar al manual, o todavía no se entienda bien, llegan...