Tema 22. Godot Engine. Disparos
Muchos juegos, según la temática, implementan disparos en sus personajes. Ejemplos más comunes pueden ser juegos de naves espaciales o de guerra donde los personajes deben eliminar a sus enemigos mediante el uso de disparos.
Vamos a ver cómo se implementan los disparos con Godot.
Para crear un proyectil, necesitaremos usar el Nodo Área2D. Lo renombramos a Proyectil.
Para poder darle animación, creamos un Nodo hijo de tipo AnimatedSprite
Ahora en AnimatedSprite creamos un New Frame con una animación llamada disparo y arrastramos los assets del proyectil que tenemos guardados previamente en el proyecto. Activamos el loop.
Además, también podemos redimensionarlo y hacerlo un poco más pequeño desde el área de la escena del proyecto.
Y como siempre, tendremos que crear un Nodo CollisionShape2D para el proyectil. Al ser redondo el proyectil, podemos asignar una forma redonda a la colisión y la ajustamos.
Creamos un script para el Nodo Proyectil y declaramos lo siguiente:
extends Area2D export var Speed = 100 var velocity = Vector2() # Called when the node enters the scene tree for the first time. func _ready(): pass # Replace with function body. # Called every frame. ‘delta’ is the elapsed time since the previous frame. func _process(delta): velocity.x = Speed * delta translate(velocity) |
Para que se mueva usamos la función translate.
Si probamos a hacer Play en el Nodo Proyectil, observaremos que sale disparado de izquierda a derecha en la parte superior de la pantalla.
Comprobaremos que no tiene animación. Hay que añadir la siguiente línea al código para darle animación:
func _process(delta): velocity.x = Speed * delta translate(velocity) $AnimatedSprite.play(«disparo») |
Ahora añadiremos el Nodo VisibilityNotifier2D como hijo del Nodo Proyectil. Este nodo nos servirá para situar el proyectil en una posición específica en el Player.
Este Nodo lo conectaremos con una función: screen_exited() que nos informa cuando el Nodo abandona la pantalla. Esta función es muy útil porque en ella usaremos la función de borrar el Nodo Proyectil cuando éste sale de la pantalla.
Ahora en el Script veremos la siguiente función:
func _on_VisibilityNotifier2D_screen_exited(): pass # Replace with function body. |
Y hacemos la siguiente modificación:
func _on_VisibilityNotifier2D_screen_exited(): queue_free() |
Ahora cada vez que el área del proyectil se salga de la pantalla, se eliminará.
Ahora tenemos que enganchar el Nodo Proyectil con el Nodo Player. Para ello vamos al Script del Nodo Player y declaramos lo siguiente:
Con este código asignamos a PROYECTIL las “características” de LA ESCENA Proyectil, es decir, la variable PROYECTIL, es un objeto de tipo Proyectil Escena.
var PROYECTIL = preload(«res://Proyectil.tscn») |
Ahora iremos a las acciones y crearemos una acción para el botón para disparar. En este ejemplo usaremos la barra de espacio. A la acción la llamamos Shoot.
Y el código cuando presionamos la tecla Space en el Player quedará así:
if Input.is_action_just_pressed(«Shoot»): var midisparo = PROYECTIL.instance() get_parent().add_child(midisparo) |
Y lo movemos en el lugar donde deseamos que salga el Proyectil:
Y vamos al código del Player y por código asignamos al Proyectil, la posición del Nodo Position2D que hemos establecido en el Nodo Player.
midisparo.position = $Position2D.global_position |
Y el código completo del Player quedará así:
extends KinematicBody2D export var Velocidad1 = 200 var velo1 = Vector2() const PROYECTIL = preload(«res://Proyectil.tscn») # Declare member variables here. Examples: # var a = 2 # var b = «text» # Called when the node enters the scene tree for the first time. func _ready(): pass # Called every frame. ‘delta’ is the elapsed time since the previous frame. func _process(delta): velo1.y += Velocidad1 * delta if Input.is_action_pressed(«Player_Left»): $AnimatedSprite.flip_h = true; $AnimatedSprite.play(«left») velo1.x = -Velocidad1 if Input.is_action_pressed(«Player_Right»): $AnimatedSprite.play(«right») $AnimatedSprite.flip_h = false; velo1.x = Velocidad1 if !Input.is_action_pressed(«Player_Left») and !Input.is_action_pressed(«Player_Right»): $AnimatedSprite.play(«idle») velo1.x = 0 if Input.is_action_just_pressed(«Shoot»): print(«disparo») var midisparo = PROYECTIL.instance() get_parent().add_child(midisparo) midisparo.position = $Position2D.global_position move_and_slide(velo1,Vector2(0,-1)) |
Y probamos a disparar: