Hacienda Escapist: Code & Tutorials

Episode 1

Part 1 - Movimiento de la cámara

Script para el movimiento de la camara

GDScript
    extends Node3D

var lookSensivity: float = 15.0
 #limite de rotacion
var minLookAngle : float = -20.0
var maxLookAngle : float =75.0

var mouseDelta : Vector2 = Vector2()

@onready var jugador = get_parent()

func _ready():
	#Ocultar el cursor
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event):
	if event is InputEventMouseMotion:
		mouseDelta=event.relative
		
func _process(delta):
	var rot=Vector3(mouseDelta.y, mouseDelta.x, 0) * lookSensivity * delta
	
	rotation_degrees.x-=rot.x
	rotation_degrees.x=clamp(rotation_degrees.x, minLookAngle, maxLookAngle)
	
	jugador.rotation_degrees.y-= rot.y
	
	
	mouseDelta=Vector2()
  

Part 2 - Jugador

Script que contiene todos los datos del jugador como la vida y las acciones que puede realizar, moverse, saltar, golpear

GDScript
    extends CharacterBody3D
var currentHealth : int = 10
var maxHealth : int = 10
var damage : int = 1
var gold : int = 0
var attackRate : float = 0.3
var lastAttackTime : int = 0
var moveSpeed : float = 5.0
var jumpForce : float = 5.0
var gravity : float = 20.0
var vel : Vector3 = Vector3()
@onready var camera = $CameraPivot
@onready var animacion = $PortaEspada/Animacion
@onready var attackRayCast = $RayCast3D
@onready var ui =$"../CanvasLayer/UI"

#Llamamos a los metodos de la interfaz para establecer al inicio la vida y el numero de los coleccionables
func _ready ():
	ui.update_health_bar(currentHealth, maxHealth)
	ui.update_gold_label(gold)


#Si el jugador pulsa el ataque este intentara atacar
func _process(delta):
	if Input.is_action_just_pressed("ataque"):
		try_attack()


func try_attack ():
	#Hacemos que el jugador no pueda atacar muy rapido
	if Time.get_ticks_msec() - lastAttackTime < attackRate * 1000:
		return
		
	lastAttackTime = Time.get_ticks_msec()
	
	#Reproducimos la animacion
	animacion.stop()
	animacion.play("attack")
	
	#Si el raycast esta colisionando con el enemigo inflingimos daño
	if attackRayCast.is_colliding():
		if attackRayCast.get_collider().has_method("take_damage"):
			attackRayCast.get_collider().take_damage(damage)

func _physics_process(delta):
	
	#Movemos al jugador, esto nos devuelve un Vector2
	var input_dir = Input.get_vector( "mover_izquierda", "mover_derecha", "mover_delante", "mover_atras")
	var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	velocity.x = direction.x * moveSpeed
	velocity.z = direction.z * moveSpeed
	#Si no esta en el suelo hacemos que caiga
	if not is_on_floor():
		velocity.y -= gravity * delta
	
	#Si pulsa saltar y esta en el suelo el jugador salta
	if Input.is_action_pressed("saltar") and is_on_floor():
		velocity.y = jumpForce

	move_and_slide()
	
	#Aumentamos la cantidad de coleccionables recogidos
func aumenta_oro (cantidad):
	gold += cantidad
	ui.update_gold_label(gold)
	
#Funcion que se ejecuta cuando el enemigo nos inflinge daño
func take_damage (damageToTake):
	currentHealth -= damageToTake
	#Se actualiza la barra de vida
	ui.update_health_bar(currentHealth, maxHealth)
	
# 	Si la vida llega a 0 morimos
	if currentHealth <= 0:
		die()
		
#Cuando morimos cambiamos la escena a la escena de muerte
func die():
	get_tree().change_scene_to_file("res://death.tscn")


  

Part 3 - Enemigo

Script para el movimiento y el ataque del enemigo

GDScript
    extends CharacterBody3D
@onready var jugador : Node3D =$"../Jugador"
@onready var navigation_agent:NavigationAgent3D = $NavigationAgent3D
var rapidez=4.0
var currentHealth : int= 20
var maxHealth : int=20
var damage: int =1
var attackDist:float=1.5
var attackRate:float = 1.0
var lastAttackTime:int = 0
func _physics_process(delta):
	
	if navigation_agent.is_navigation_finished():
		return
	#Coordenadas del siguiente punto a moverse
	var next_path_position=navigation_agent.get_next_path_position()
	#Se calcula el vector normalizado para llegar a ese punto
	velocity =global_position.direction_to(next_path_position)*rapidez
	move_and_slide()



func _on_timer_timeout():
	navigation_agent.target_position=jugador.global_position

#Funcion cuando el jugador inflinge daño
func take_damage(damageToTake):
	#restamos a la vida actual el daño realizado
	currentHealth-=damageToTake
	#Si llega a 0 el enemigo muere
	if currentHealth<=0:
		die()
func die():
	queue_free()
	
#Si esta el enemigo a la distancia de ataque este atacara inflingiendo daño al jugador
func _on_timer_2_timeout():
	if global_position.distance_to(jugador.global_position)<=attackDist:
		jugador.take_damage(damage)

  

Part 4 - Muerte

Script para el menú de muerte, las frases de muerte serán 3 que aparecerán aleatoriamente. Además cuenta con poder rejugar y salir del programa

GDScript
    extends CanvasLayer
#Obtenemos el label para la derrota
@onready var deathLabel=$PanelContainer/MarginContainer/VBoxContainer/Label
#Creamos un random
var rng = RandomNumberGenerator.new()
func _ready():
	#Hacemos que se pueda capturar el raton
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
	#Hacemos un random de 1 a 3 para ir cambiando el texto de la derrota
	var my_random_number =randi_range(1, 3)
	print(my_random_number)
	if my_random_number==1:
		deathLabel.text="Pagaste Autónomos En España"
	if my_random_number==2:
		deathLabel.text="Te Embargaron Los Pisos De Barcelona"
	if my_random_number==3:
		deathLabel.text="No Conseguiste Desahuciar A La Abuela Del Piso"
	
#Funcion para volver a empezar el juego cuando se pulsa el boton
func _on_reintentar_pressed():
	get_tree().change_scene_to_file("res://main.tscn")

#Funcion para abandonar el juego cuando se pulsa el boton
func _on_salir_pressed():
	get_tree().quit()

  

Part 5 - Ganar

Igual que el de Muerte

GDScript
    extends CanvasLayer
#Obtenemos el label para la derrota
@onready var deathLabel=$PanelContainer/MarginContainer/VBoxContainer/Label
#Creamos un random
var rng = RandomNumberGenerator.new()
var muertes=["Pagaste Autónomos En España", "Te Embargaron Los Pisos De Barcelona", "No Conseguiste Desahuciar A La Abuela Del Piso"]
func _ready():
	#Hacemos que se pueda capturar el raton
	Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
	#Hacemos un random de 1 a 3 para ir cambiando el texto de la derrota
	var my_random_number =randi_range(0, 2)
	deathLabel.text=muertes[my_random_number]

	
#Funcion para volver a empezar el juego cuando se pulsa el boton
func _on_reintentar_pressed():
	get_tree().change_scene_to_file("res://main.tscn")

#Funcion para abandonar el juego cuando se pulsa el boton
func _on_salir_pressed():
	get_tree().quit()

  

Part 6

Si el jugador entra en la zona se cambia la escena

GDScript
    extends Node3D
#Si el jugador llega al area final cambiamos la escena
func _on_area_3d_body_entered(body):
	if body.name=="Jugador":
		get_tree().change_scene_to_file("res://ganar.tscn")

  

Part 7 - Moneda

Script para hacer una animacion de una moneda mediante script haciendo que rote

GDScript
    extends Area3D
@export var valor:int=1
var velocidadRotacion : float =5.0
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	#Rotamos el objeto para realizar una animacion
	rotate_y(velocidadRotacion*delta)

#Si el jugador toca la moneda el contador aumenta
func _on_body_entered(body):
	if body.name=="Jugador":
		body.aumenta_oro(valor)
		queue_free()
  

Part 8 - Interfaz

Interfaz del juego, controla las monedas que hemos recogido y la vida del personaje

GDScript
    extends Control
#Obtenemos el Label y la barra de vida
@onready var healthBar=$HealthBar
@onready var goldLabel=$Gold

#Metodo para actaulizar la barra de vida
func update_health_bar(currentHp, maxHp):
	healthBar.value=(100/maxHp) * currentHp
#Metodo para actualizar el contador
func update_gold_label(gold):
	goldLabel.text="Primes: " + str(gold)