0% encontró este documento útil (0 votos)
93 vistas30 páginas

Clases Godot

El documento proporciona una guía sobre el uso de clases y objetos en Godot, destacando conceptos clave como la herencia, polimorfismo y la organización de escenas. También aborda la física básica, colisiones y la implementación de ciclos de procesos para el control del juego. Finalmente, se discuten aspectos de modularidad, encapsulamiento y la creación de interfaces de usuario en el contexto de un juego de naves espaciales.

Cargado por

jmgoya
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
93 vistas30 páginas

Clases Godot

El documento proporciona una guía sobre el uso de clases y objetos en Godot, destacando conceptos clave como la herencia, polimorfismo y la organización de escenas. También aborda la física básica, colisiones y la implementación de ciclos de procesos para el control del juego. Finalmente, se discuten aspectos de modularidad, encapsulamiento y la creación de interfaces de usuario en el contexto de un juego de naves espaciales.

Cargado por

jmgoya
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd

Clase 1..........................................................................................................................................

3
1. Fundamentos: Clases y Objetos en Godot........................................................................3
1.1. Clases en Godot......................................................................................................3
1.2. Objetos en Godot...................................................................................................3
1.3. Tipos de objetos y su jerarquía...............................................................................3
1.4. Usar Escenas como Clases......................................................................................4
1.5. Organización en Escenas y Nodos...........................................................................4
1.6. Ejemplo Práctico: Nave Espacial (Ship)...................................................................4
1.7. Principios de la POO en el Proyecto de Naves Espaciales.......................................4
1.8. Herencia en Godot..................................................................................................5
1.9. Creación de la Clase Base (Nave.gd).......................................................................5
1.10. Creación de las Clases Derivadas............................................................................5
1.11. Ventajas de la Herencia en Godot..........................................................................6
2. Física Básica, Colisiones y Ciclos de Procesos en Godot...................................................7
2.1. Física Básica............................................................................................................7
2.2. Colisiones................................................................................................................7
2.3. Ciclos de Procesos: _process, _physics_process y _input.......................................8
2.4. Ejemplo Integrado en el Juego de Naves Espaciales...............................................9
3. Herencia y Polimorfismo con Nodos y Escenas en Godot...............................................10
3.1. Polimorfismo en Godot.........................................................................................10
3.2. Uso de Nodos y Escenas con Herencia y Polimorfismo.........................................10
3.3. Ejemplo en la Escena Principal..............................................................................10
3.4. Ventajas del Polimorfismo en el Juego de Naves..................................................11
4. Señales, Singletons y Variables Globales........................................................................12
4.1. Señales en Godot..................................................................................................12
4.2. Singletons.............................................................................................................12
4.3. Eventos (Mediante Señales).................................................................................13
4.4. Variables Globales................................................................................................13
4.5. Registros y Gravaciones en un Singleton..............................................................14
4.5.1. Creando un Singleton para Registros................................................................14
4.5.2. Grabaciones en Archivos..................................................................................15
5. Introducción a la Modularidad.......................................................................................16
5.1. Uso de Funciones para Reutilización de Código....................................................16
5.2. Encapsulamiento para Controlar el Acceso a los Datos........................................16
5.3. Código Limpio: Nombres Descriptivos y Comentarios..........................................16
5.4. Separación de Lógica en Clases Especializadas.....................................................17
5.5. Ejercicio Final: Aplicación de los Principios en el Código Completo de la Nave....17
6. Interfaz de Usuario: Registro de Puntuación y Configuraciones en el Juego de Naves
Espaciales...............................................................................................................................18
6.1. Tipos de Nodos Control........................................................................................18
6.2. Diferencias con Otros Nodos................................................................................18
6.3. Configuración Básica de Música y Efectos............................................................19
6.4. Menú Principal y Reinicio del Juego......................................................................19
6.5. Registro de Puntuación y Guardado de Variables.................................................19
6.6. Configuración Básica de Sonido (Música, Efectos, y Mute)...................................20
6.7. Menú Principal y Reinicio del Juego......................................................................21
7. Integración Final y Exportación del Juego de Naves Espaciales......................................23
7.1. Integración Final del Proyecto..............................................................................23
7.2. Exportación del Juego...........................................................................................24
7.3. Empaquetado y Publicación del Juego..................................................................24
Clase 1
1. Fundamentos: Clases y Objetos en Godot
En Godot, los conceptos de clases y objetos están representados de una forma única y
visual a través de nodos y escenas. Este enfoque permite a los desarrolladores
visualizar la estructura y organización del código mientras utilizan las ventajas de la
Programación Orientada a Objetos (POO). Explicaremos estos conceptos
fundamentales y cómo se aplican en Godot.

1.1. Clases en Godot


o Concepto: En programación orientada a objetos, una clase es un plano o
plantilla a partir de la cual se crean objetos. Una clase define atributos
(propiedades) y métodos (funciones) que los objetos creados a partir de ella
compartirán.
o Ejemplo en Godot: En Godot, cada script adjunto a un nodo es una clase que
extiende de alguna clase base (como Node2D, Control, o Area2D).
o Al crear un nuevo script en Godot y asociarlo con un nodo, estás definiendo
una nueva clase. Por ejemplo, un script para una nave (Ship.gd) puede ser
una clase que extienda Node2D, lo que convierte a Ship en una subclase de
Node2D.

gdscript

extends Node2D # Esto indica que este nodo es una


subclase de Node2D

var velocidad = 200 # Atributo

func mover(): # Método


position.x += velocidad * delta

o Creación de Instancias: En el juego, una clase no es útil por sí sola hasta que se
crea una instancia de ella, es decir, un objeto. Cada objeto creado a partir de
Ship.gd tendrá sus propios valores para velocidad, posición, etc., lo que
le permite funcionar de manera independiente en el juego.

1.2. Objetos en Godot


 Concepto: Un objeto es una instancia concreta de una clase, que puede tener
sus propios valores para los atributos definidos en la clase.
 Ejemplo en Godot: Al agregar un nodo de nave (Ship) a la escena, estás
creando un objeto de la clase Ship.
 En el proyecto de naves espaciales, la nave del jugador será un objeto de la
clase Ship. Cada enemigo, a su vez, puede ser un objeto de una clase Enemy.
 En Godot, puedes tener múltiples instancias de la misma clase en una escena,
cada una con valores únicos para sus propiedades.

1.3. Tipos de objetos y su jerarquía


Veremos el árbol de objetos que nos ofrece Godot

 Nodos 2D
o Sprite
o Area2D
o

1.4. Usar Escenas como Clases


 Escenas como Plantillas: En Godot, puedes usar una escena como plantilla
para un objeto, de forma similar a una clase. Cuando se crea una escena para
la nave (Ship.tscn), puedes reutilizarla en diferentes partes del juego.
 Ejemplo en el Juego:
o Crea una escena Ship.tscn con un nodo Node2D como raíz y el
script Ship.gd asociado a él.
o Al instanciar Ship.tscn en la escena principal del juego, estás
creando un objeto de la clase Ship.

1.5. Organización en Escenas y Nodos


 Estructura de un Juego Basado en Objetos: La estructura de un juego en Godot
refleja la estructura de objetos en POO:
 Nodos: Son instancias de clases en Godot. Representan todo tipo de objetos
en el juego (jugadores, enemigos, HUD, etc.).
 Escenas: Son estructuras organizadas de nodos. Pueden representar una
entidad completa (por ejemplo, una nave) o una parte de la interfaz del juego.

1.6. Ejemplo Práctico: Nave Espacial (Ship)


 Creación de la Clase Nave (Ship.gd):

o Crea un script Ship.gd para la nave del jugador, con propiedades como
velocidad y vida, y métodos como mover y disparar.
o Este script define la clase Ship que podemos usar en el juego.
gdscript

extends Node2D

var velocidad = 200


var vida = 3

func mover(direccion: Vector2):


position += direccion * velocidad * delta
 Instanciación de la Nave:
o Crea una escena Ship.tscn y agrega Ship.gd a la escena.
o Al arrastrar Ship.tscn a la escena principal, creas una instancia
(objeto) de Ship.
o Esto permite que haya varios objetos Ship, si el juego lo requiere.

1.7. Principios de la POO en el Proyecto de Naves


Espaciales
Aplicar los principios de POO en el proyecto:

 Modularidad: Al organizar el juego en clases y objetos (como Ship, Enemy,


Projectile), cada entidad tiene sus propias responsabilidades y código. Esto
facilita agregar, modificar o eliminar características.
 Reutilización: Crear una clase Enemy permite instanciar enemigos en
diferentes niveles sin duplicar código.
 Encapsulación: Las variables y métodos específicos de la nave (velocidad,
disparar) están contenidos en Ship, evitando interacciones no deseadas
con otros nodos.

1.8. Herencia en Godot


La herencia permite crear nuevas clases basadas en otras existentes, heredando todas
las propiedades y métodos de la clase base. En Godot, esto se logra extendiendo una
clase mediante scripts.

 Clase Base y Clases Derivadas:


o Una clase base define los atributos y comportamientos comunes que serán
compartidos por todas las clases derivadas.
o Las clases derivadas pueden agregar o modificar comportamientos
específicos.
 Ejemplo en el Proyecto de Naves Espaciales:
o Supongamos que tenemos diferentes tipos de naves en el juego: una nave
del jugador y naves enemigas. Podemos definir una clase base llamada
Nave que contenga propiedades y métodos comunes (como vida,
velocidad, y mover()).
o Luego, las clases NaveJugador y NaveEnemiga pueden heredar de Nave
y añadir o sobrescribir comportamientos específicos.

1.9. Creación de la Clase Base (Nave.gd)

 Define un script para la clase base Nave con las propiedades y métodos
comunes:
gdscript

# Nave.gd
extends Node2D

var velocidad: float


var vida: int

func mover(direccion: Vector2):


position += direccion * velocidad * delta

func recibir_dano(dano: int):


vida -= dano
if vida <= 0:
morir()

func morir():
queue_free() # Elimina el nodo de la escena

 En Nave.gd se definen las propiedades velocidad y vida, y los métodos


mover, recibir_dano, y morir.
 Esta clase ahora sirve como plantilla para las clases derivadas.
1.10. Creación de las Clases Derivadas
 Nave del Jugador (NaveJugador.gd)

o Define un nuevo script NaveJugador.gd que extiende la clase Nave.


o Añade comportamientos específicos, como la capacidad de disparar, y
ajusta la velocidad o vida según el diseño de la nave del jugador.
gdscript

# NaveJugador.gd
extends "res://Nave.gd"

func disparar():
# Código para instanciar y disparar proyectiles
var proyectil = Projectile.instance()
proyectil.position = position
get_parent().add_child(proyectil)

 Nave Enemiga (NaveEnemiga.gd)

o Define otro script NaveEnemiga.gd que también extiende Nave.


o Añade patrones de movimiento o comportamientos específicos, como
perseguir al jugador o moverse en patrones predefinidos.
gdscript

# NaveEnemiga.gd
extends "res://Nave.gd"

func mover_automatico():
# Código para definir un patrón de movimiento
específico para enemigos
position += Vector2(-1, 0) * velocidad * delta

1.11. Ventajas de la Herencia en Godot


 Código Reutilizable: NaveJugador y NaveEnemiga comparten los métodos y
propiedades comunes de Nave, lo que evita la duplicación de código.
Facilidad para Agregar Nuevas Entidades: Si en el futuro se agregan nuevos tipos de naves
(por ejemplo, una nave aliada), pueden extender Nave y heredar su comportamiento,
permitiendo un desarrollo más rápido y

Este enfoque ayuda a introducir a los estudiantes en el uso de POO, tanto desde el
punto de vista teórico como práctico, permitiéndoles visualizar el poder de las clases y
objetos a medida que avanzan en la construcción de su juego de naves espaciales en
Godot.
2. Física Básica, Colisiones y Ciclos de Procesos en
Godot
Este apartado cubre los fundamentos de física y detección de colisiones en Godot,
junto con el uso de los métodos especiales _process, _physics_process e _input para
controlar el flujo y la interacción del juego. Estos conceptos son esenciales para
gestionar el movimiento, la interacción entre objetos y las respuestas a la entrada del
jugador en el juego.

2.1. Física Básica


Godot ofrece un motor de física incorporado que permite gestionar dinámicas como
movimiento, gravedad, fricción y rebotes. Las físicas en Godot funcionan
principalmente a través de nodos específicos, como RigidBody2D y KinematicBody2D
(o sus equivalentes en 3D), cada uno con características y comportamientos
particulares:

 RigidBody2D: Un nodo de cuerpo físico controlado por el motor de física de


Godot. Este tipo de nodo simula la física real, aplicando fuerza y gravedad
automáticamente. Es ideal para objetos que deben tener movimientos
realistas y responde a colisiones sin programación adicional.
 KinematicBody2D: Este nodo permite un control más directo sobre el
movimiento del objeto. Con el método move_and_slide() o
move_and_collide(), el desarrollador controla el movimiento, y el motor
de física se encarga de detectar y manejar las colisiones.
 StaticBody2D: Un cuerpo fijo, utilizado para objetos que no necesitan
movimiento, pero que otros cuerpos pueden colisionar contra él, como
paredes o plataformas.
 En el contexto del juego de naves espaciales, podemos utilizar un
KinematicBody2D para la nave del jugador, permitiéndole moverse
libremente mientras detecta colisiones con meteoritos u otros elementos del
entorno.

2.2. Colisiones
Las colisiones son una parte fundamental de la interacción entre objetos en Godot.
Para gestionar colisiones, necesitamos:

 CollisionShape2D: Un nodo que define la forma de colisión de un objeto. Esto


permite al motor de física detectar cuando dos objetos están en contacto.
 Métodos de detección: En el caso de los KinematicBody2D, podemos usar
move_and_collide() para detectar si ha habido una colisión o
move_and_slide() para deslizar el objeto por superficies.

Ejemplo básico de uso en un KinematicBody2D:


gdscript

extends KinematicBody2D

var velocity = Vector2.ZERO


func _physics_process(delta):
# Actualizamos el movimiento
velocity = Vector2(100, 0)
var collision_info = move_and_collide(velocity *
delta)

if collision_info:
print("¡Colisión detectada!")

En este ejemplo, cada vez que el cuerpo colisiona con otro, se imprime un mensaje.
Este mecanismo es útil para la detección de colisiones en el juego de naves espaciales,
por ejemplo, al detectar cuando la nave colisiona con un asteroide.

2.3. Ciclos de Procesos: _process, _physics_process y


_input
Estos tres métodos son fundamentales para controlar el flujo del juego:

 _process(delta):

o Es llamado en cada cuadro, a una velocidad que puede variar


dependiendo de la tasa de fotogramas del dispositivo.
o Ideal para actualizar elementos que no dependen de la física, como
animaciones o movimientos visuales.
o Ejemplo de uso:
o gdscript
o Copiar código
o func _process(delta):
position.x += 10 * delta # Mover a la derecha

 _physics_process(delta):

o Es llamado en intervalos fijos de tiempo (normalmente 60 veces por


segundo) independientemente de la velocidad de fotogramas,
garantizando una actualización constante de la física.
o Ideal para manejar el movimiento y la lógica que dependa de la física.
o Ejemplo de uso:
o gdscript
o Copiar código
o func _physics_process(delta):
position.y += 10 * delta # Movimiento físico hacia
abajo

 _input(event):

o Detecta cualquier tipo de entrada del usuario, ya sea teclado, ratón o


controlador de juego.
o Útil para manejar los controles del jugador y responder a eventos
como clics y teclas presionadas.
o Ejemplo de uso:
gdscript

func _input(event):
if event.is_action_pressed("ui_right"):
position.x += 10
if event.is_action_pressed("ui_left"):
position.x -= 10

2.4. Ejemplo Integrado en el Juego de Naves Espaciales


Imaginemos que la nave espacial se mueve en todas las direcciones usando el teclado,
y se enfrenta a colisiones con asteroides u obstáculos. Aquí se demuestra cómo
podríamos implementar estas físicas básicas y la detección de colisiones:
gdscript

extends KinematicBody2D

var velocity = Vector2.ZERO


var speed = 200

func _physics_process(delta):
velocity = Vector2.ZERO

# Control de movimiento
if Input.is_action_pressed("move_right"):
velocity.x += 1
if Input.is_action_pressed("move_left"):
velocity.x -= 1
if Input.is_action_pressed("move_up"):
velocity.y -= 1
if Input.is_action_pressed("move_down"):
velocity.y += 1

# Normalizar para mantener velocidad constante en


diagonales
velocity = velocity.normalized() * speed

# Movimiento con colisión


var collision_info = move_and_collide(velocity *
delta)

if collision_info:
print("¡Colisión detectada!")
# Puedes agregar lógica de daño o respuesta a
la colisión

Este script permite que la nave responda a las teclas de dirección (arriba, abajo,
izquierda y derecha) y se detiene o reacciona al chocar con otro objeto en el juego.
3. Herencia y Polimorfismo con Nodos y Escenas en
Godot
La herencia y el polimorfismo son principios avanzados de la Programación Orientada
a Objetos (POO) que permiten crear estructuras de código reutilizables y flexibles. En
Godot, estos principios son especialmente útiles cuando se trabaja con nodos y
escenas, ya que permiten estructurar comportamientos comunes y específicos para
diferentes entidades dentro del juego. Aquí te explico cómo aplicar estos conceptos en
Godot y en nuestro proyecto de naves espaciales.

 organizado.

3.1. Polimorfismo en Godot


El polimorfismo permite que un objeto de una clase derivada se trate como si fuera de
la clase base. Esto significa que las funciones de la clase base pueden actuar sobre las
instancias de las clases derivadas, incluso si cada una de estas implementa el método
de forma distinta.

 Ejemplo en el Proyecto de Naves Espaciales:

o Supongamos que el juego tiene una lista de Nave (que incluye


NaveJugador y NaveEnemiga). Si llamamos a mover() en cada
elemento de la lista, el método adecuado de cada clase derivada se
ejecutará automáticamente.
o Esto es posible porque NaveJugador y NaveEnemiga implementan
su propio método mover().
gdscript

# Ejemplo de polimorfismo
var naves = [NaveJugador.new(), NaveEnemiga.new()]

for nave in naves:


nave.mover(Vector2(1, 0)) # Llama al mover() de cada
clase específica

3.2. Uso de Nodos y Escenas con Herencia y Polimorfismo


 Uso de Escenas como Plantillas:

o Crea una escena Nave.tscn como plantilla base para las naves y
configúrala con nodos comunes, como una animación, un
CollisionShape2D y un sprite.
o Para NaveJugador.tscn y NaveEnemiga.tscn, hereda de
Nave.tscn y ajusta los valores específicos en cada escena.

 Diferencias en el Comportamiento con el Polimorfismo:

o Las escenas instanciadas en la escena principal pueden actuar según el


tipo de clase específico (jugador o enemigo) cuando se llaman
métodos compartidos.
3.3. Ejemplo en la Escena Principal
Este código en la escena principal itera sobre las naves en pantalla y aplica diferentes
métodos dependiendo de su clase específica:
gdscript

# Escena principal
extends Node2D

var naves = [] # Almacena instancias de naves

func _ready():
# Instancia las naves y agrega a la lista
var nave_jugador =
load("res://NaveJugador.tscn").instance()
add_child(nave_jugador)
naves.append(nave_jugador)

var nave_enemiga =
load("res://NaveEnemiga.tscn").instance()
add_child(nave_enemiga)
naves.append(nave_enemiga)

func _process(delta):
for nave in naves:
nave.mover(Vector2(1, 0)) # Llama al método de
mover de cada clase específica
3.4. Ventajas del Polimorfismo en el Juego de Naves
 Interacción Flexible entre Objetos: Puedes crear listas o grupos de objetos de
clase base Nave y hacer que cada uno responda según su implementación.
 Código Limpio y Escalable: Puedes agregar nuevos tipos de naves o
variaciones sin modificar el código de la escena principal.

Con esta estructura, puedes enseñar conceptos complejos como herencia y


polimorfismo en un contexto visual e interactivo. Usando nodos y escenas, los
estudiantes pueden ver cómo se aplican estos principios al crear y manipular
diferentes tipos de naves, lo cual hace que los fundamentos de POO sean intuitivos y
prácticos.
4. Señales, Singletons y Variables Globales
Las señales, singletons y variables globales son herramientas esenciales para
comunicar diferentes partes de un juego, especialmente en Godot. En un juego de
naves, pueden ser utilizados para comunicar eventos clave como colisiones, cambios
en la puntuación y estado del jugador.

4.1. Señales en Godot


 Concepto: Las señales son una forma de emitir eventos y permitir que otros
nodos reaccionen a ellos sin necesidad de que estén conectados directamente.
Son útiles para mantener la independencia entre clases.
 Ejemplo en el Juego: Al disparar o destruir un enemigo, la nave puede emitir
una señal que actualice la puntuación del jugador sin necesidad de que la nave
sepa cómo funciona el sistema de puntuación.
 Cómo Usarlas:

o Definir una señal: En el script de la nave (por ejemplo, Ship.gd),


define la señal:
gdscript

signal disparo_realizado
signal enemigo_destruido()
o Emitir la señal: Llama a la señal cuando ocurra el evento relevante,
como al disparar o destruir un enemigo:
gdscript

func disparar():
# Código para disparar un proyectil
emit_signal("disparo_realizado")

func destruir_enemigo():
# Código para destruir un enemigo
emit_signal("enemigo_destruido")

o Conectar la señal: En otro nodo (por ejemplo, en el controlador de


puntuación), conecta esta señal para responder al evento:
gdscript

ship.connect("enemigo_destruido", self,
"_actualizar_puntaje")
func _actualizar_puntaje():
puntaje += 10

4.2. Singletons
 Concepto: Los singletons, también conocidos como Autoloads en Godot, son
scripts que se cargan al iniciar el juego y están disponibles globalmente. Esto
permite almacenar variables y métodos accesibles desde cualquier lugar del
proyecto.
 Ejemplo en el Juego: Crear un singleton GameManager que almacene la
puntuación del jugador, el estado de vida y otra información general del juego.
 Cómo Usarlos:
o Crear el Singleton: Crea un script llamado GameManager.gd y define
las variables globales, como puntuacion y vida.
gdscript

# GameManager.gd
var puntuacion = 0
var vida = 3

func reiniciar_juego():
puntuacion = 0
vida = 3

o Agregarlo como Singleton: En el menú de Godot, ve a Project >


Project Settings > Autoload y agrega el script GameManager.gd. Así
estará disponible en todo el proyecto como GameManager.
o Usar el Singleton: Ahora, puedes acceder a las variables y métodos de
GameManager desde cualquier script:

gdscript

GameManager.puntuacion += 10
GameManager.reiniciar_juego()

4.3. Eventos (Mediante Señales)


 Concepto: Los eventos en Godot son situaciones o cambios en el juego que
otros elementos deben conocer y responder, como cuando el jugador pierde
una vida, gana puntos, o completa un nivel.
 Ejemplo en el Juego: Emitir una señal de evento vida_perdida cuando la
nave del jugador colisiona con un enemigo o proyectil enemigo.
 Cómo Usarlos:

o Definir y Conectar Eventos: En el script Ship.gd, define y conecta


señales como vida_perdida.
gdscript

signal vida_perdida

func _on_colision_con_enemigo():
GameManager.vida -= 1
emit_signal("vida_perdida")

o Reaccionar al Evento en Otro Script: En un script de UI o de Game Over,


reacciona a la señal para actualizar la interfaz o finalizar el juego:

gdscript

ship.connect("vida_perdida", self, "_actualizar_vida_ui")

4.4. Variables Globales


 Concepto: Las variables globales permiten almacenar datos accesibles en todo
el proyecto, como el puntaje o el nivel. Estas variables suelen manejarse
mediante singletons o autoloads para una organización adecuada.
 Ejemplo en el Juego: Usar GameManager para almacenar y manejar variables
como nivel_actual, vidas_restantes, o puntaje_total.
 Cómo Usarlas:

o Definir Variables Globales: Dentro de GameManager.gd, define


variables como nivel_actual o puntaje_total.
gdscript

var nivel_actual = 1
var puntaje_total = 0

o Acceder desde Otro Script: Puedes acceder a


GameManager.nivel_actual o GameManager.puntaje_total desde
cualquier otro script para controlar el flujo del juego:
gdscript

if GameManager.vidas <= 0:
cambiar_a_escena_game_over()

4.5. Registros y Gravaciones en un Singleton

Los singletons (también conocidos como nodos globales) son nodos que se instancian
una sola vez y permanecen en la memoria durante toda la ejecución del juego. Se
utilizan comúnmente para gestionar datos globales, como configuraciones,
puntuaciones y estados del juego.

4.5.1. Creando un Singleton para Registros


 Creación del Singleton:

o En Godot, crea un nuevo script llamado Global.gd.


o Asegúrate de que este script extienda Node o Object y que contenga
las variables necesarias para almacenar los registros del jugador y las
configuraciones.
gdscript

extends Node

var player_scores = []
var settings = {
"music_volume": 1.0,
"sfx_volume": 1.0,
"is_muted": false,
}
 Configuración del Singleton:

o Ve a Project > Project Settings > AutoLoad.


o Agrega el script Global.gd como un singleton. Esto hará que esté
disponible en cualquier parte del juego.
 Manejando Registros:

o Puedes agregar funciones en el script Global.gd para guardar, cargar


y modificar los registros del jugador. Aquí un ejemplo básico de cómo
agregar una puntuación:
gdscript

func add_score(score: int):


player_scores.append(score)
save_scores()

func save_scores():
var file = File.new()
if file.open("user://scores.save", File.WRITE) == OK:
for score in player_scores:
file.store_line(str(score))
file.close()
4.5.2. Grabaciones en Archivos
Para guardar y cargar registros de puntuaciones, puedes utilizar archivos. En el
ejemplo anterior, se guarda la lista de puntuaciones en un archivo en el sistema del
usuario. Para cargar las puntuaciones al iniciar el juego, puedes hacer lo siguiente:
gdscript
Copiar código
func load_scores():
var file = File.new()
if file.open("user://scores.save", File.READ) ==
OK:
player_scores.clear()
while not file.eof_reached():
player_scores.append(int(file.get_line()))
file.close()
5. Introducción a la Modularidad
 Objetivo: Explicar qué es la modularidad y por qué es crucial en desarrollo de
software.
 Concepto: La modularidad implica dividir el código en partes pequeñas e
independientes (módulos) que realizan tareas específicas.
 Ejemplo en el Juego: Crear una clase Ship que actúe como el "módulo base"
para las naves. Esta clase incluirá solo la lógica fundamental que comparten
todas las naves, como moverse, disparar, y recibir_daño.
 Actividad: Implementar una clase Ship.gd con un método mover() que
permita cambiar la posición de la nave de acuerdo a una velocidad
predeterminada.

5.1. Uso de Funciones para Reutilización de Código


 Objetivo: Enseñar cómo crear funciones que encapsulan tareas comunes,
haciéndolas fáciles de reutilizar en distintas partes del código.
 Concepto: Las funciones deben realizar una sola tarea específica y clara. Esto
facilita que el código sea reutilizable y adaptable.
 Ejemplo en el Juego: Crear métodos como disparar(), que se encarga de
generar proyectiles, y tomar_daño(damage), que resta puntos de vida a la
nave.
 Actividad: En el script Ship.gd, añadir funciones disparar() y
tomar_daño(damage). Luego, cada vez que se llame disparar() se creará
un nuevo proyectil, mientras que tomar_daño() reduce la salud de la nave.

5.2. Encapsulamiento para Controlar el Acceso a los Datos


 Objetivo: Demostrar cómo proteger variables importantes y controlar su
acceso usando el concepto de encapsulamiento.
 Concepto: El encapsulamiento implica ocultar los detalles internos de una
clase y exponer solo lo necesario mediante métodos de acceso (getters y
setters).
 Ejemplo en el Juego: Proteger la variable salud en Ship.gd, permitiendo
acceder o modificar su valor solo a través de un método como get_salud()
o recibir_daño(damage).
 Actividad: Crear una variable var _salud privada, con un método público
recibir_daño(damage) para disminuir su valor. Luego, probar el acceso y
modificación de salud exclusivamente a través de este método.

5.3. Código Limpio: Nombres Descriptivos y Comentarios


 Objetivo: Explicar la importancia de nombres de variables y métodos claros y
descriptivos, junto con comentarios útiles.
 Concepto: Un código limpio es fácil de entender y de mantener; cada función,
variable, y método debe tener un nombre intuitivo que describa su propósito.
 Ejemplo en el Juego: Usar nombres como mover(), salud, y disparar() en
lugar de abreviaciones ambiguas como mv(), hp, o atk().
 Actividad: Los estudiantes revisan su código y renombrar variables o métodos
que no sean descriptivos, añadiendo comentarios donde es necesario.
5.4. Separación de Lógica en Clases Especializadas
 Objetivo: Mostrar cómo evitar que una clase tenga demasiadas
responsabilidades separando la lógica en clases especializadas.
 Concepto: El principio de responsabilidad única indica que cada clase debe
tener un propósito claro, evitando mezclar funcionalidades que podrían estar
en otros módulos.
 Ejemplo en el Juego: Crear una clase Projectile.gd para manejar toda la
lógica de los proyectiles de la nave, en lugar de incluirla dentro de Ship.gd.
 Actividad: Implementar Projectile.gd para que contenga métodos
específicos como mover_proyectil() y verificar_impacto(). Luego,
modificar Ship.gd para que, en lugar de gestionar los proyectiles, solo llame
a disparar() para instanciar y delegar la lógica a Projectile.

5.5. Ejercicio Final: Aplicación de los Principios en el


Código Completo de la Nave
 Objetivo: Consolidar todos los principios enseñados aplicándolos en el código
completo de la nave del jugador.
 Actividad: Los estudiantes estructuran Ship.gd utilizando los métodos
modulares, creando un código claro y fácil de entender.
 Máquinas de Estado en Godot

Las máquinas de estado son una herramienta poderosa en desarrollo de videojuegos, ya que
permiten organizar y gestionar el comportamiento de personajes, enemigos o cualquier
entidad que tenga múltiples "estados" posibles (por ejemplo, caminar, correr, atacar,
defender, etc.). En Godot, podemos implementar una máquina de estado utilizando scripts,
señales y nodos, y este enfoque modular facilita mantener el código organizado y limpio,
especialmente en proyectos complejos.

1. 8.1 ¿Qué es una Máquina de Estado?

Una máquina de estado es una estructura de programación que permite a un objeto, como un
personaje o enemigo, alternar entre diferentes "estados" de comportamiento. Cada estado
tiene sus propias reglas y acciones, y la entidad puede cambiar de un estado a otro en función
de condiciones específicas o de la entrada del jugador.

Por ejemplo, un enemigo en un juego podría tener los siguientes estados:

 Patrullando: Se mueve a lo largo de un camino predefinido.

 Persiguiendo: Persigue al jugador si está en un rango cercano.

 Atacando: Ataca al jugador si está lo suficientemente cerca.

 Huyendo: Huye si su salud es baja.

2. 8.2 Implementación de una Máquina de Estado en Godot

3. Definir los Estados:

o Se recomienda utilizar enumeraciones (enum) o constantes para definir los


diferentes estados que la entidad puede tener.

o En el script del personaje, define los posibles estados:

gdscript

Copiar código

enum States {

IDLE,

PATROLLING,

CHASING,

ATTACKING,

FLEEING

4. Variable de Estado Actual:


o Define una variable que mantenga el estado actual del personaje. Puedes
inicializarla en el estado IDLE o cualquier estado inicial apropiado.

gdscript

Copiar código

var current_state = States.IDLE

5. Función de Transición de Estado:

o Crea una función que cambie de un estado a otro. Esta función actualizará la
lógica del personaje para que responda según el estado.

gdscript

Copiar código

func change_state(new_state):

current_state = new_state

match current_state:

States.IDLE:

enter_idle()

States.PATROLLING:

enter_patrolling()

States.CHASING:

enter_chasing()

States.ATTACKING:

enter_attacking()

States.FLEEING:

enter_fleeing()

6. Funciones para Cada Estado:

o Para cada estado, crea una función que defina las acciones específicas que el
personaje debe realizar. Por ejemplo:

gdscript

Copiar código

func enter_idle():

print("Enemigo en estado IDLE")

# Lógica de inactividad
func enter_patrolling():

print("Enemigo patrullando")

# Lógica de patrullaje

func enter_chasing():

print("Enemigo persiguiendo")

# Lógica de persecución

func enter_attacking():

print("Enemigo atacando")

# Lógica de ataque

func enter_fleeing():

print("Enemigo huyendo")

# Lógica de huida

7. Actualizar el Estado en _process:

o Usa la función _process(delta) para monitorear y actualizar el estado del


personaje en cada cuadro. Dependiendo de la condición, puedes hacer que el
personaje cambie de estado.

gdscript

Copiar código

func _process(delta):

match current_state:

States.IDLE:

check_for_player()

States.PATROLLING:

patrol()

check_for_player()

States.CHASING:

chase_player()

if is_close_to_player():

change_state(States.ATTACKING)
States.ATTACKING:

attack_player()

if player_is_out_of_range():

change_state(States.CHASING)

States.FLEEING:

flee()

if is_safe():

change_state(States.IDLE)

8. 8.3 Transiciones entre Estados

Las transiciones se pueden condicionar según la situación del juego, como la distancia al
jugador o el nivel de salud. Cada transición debería ser lógica y predecible para evitar que el
personaje entre en un estado inesperado.

Para hacer que las transiciones sean más limpias y seguras, puedes utilizar una estructura
como un diagrama de estados antes de implementarla en código. Esto ayuda a definir todas
las reglas de cambio de un estado a otro.

9. 8.4 Estados Anidados y Jerarquías

Para personajes complejos, puedes implementar máquinas de estado jerárquicas


(submáquinas). Por ejemplo, el estado ATTACKING podría tener sub-estados como
RANGED_ATTACK y MELEE_ATTACK. Esto permite desglosar el comportamiento en
subcomportamientos específicos, manteniendo el código modular y organizado.

10. 8.5 Usando Señales en una Máquina de Estado

Las señales son útiles para notificar cambios de estado o condiciones específicas. Por ejemplo,
podrías emitir una señal cuando el personaje ve al jugador o cuando el jugador se aleja.

gdscript

Copiar código

signal player_spotted

func check_for_player():

if is_player_in_range():

emit_signal("player_spotted")

change_state(States.CHASING)
En el nodo principal, conecta esta señal para que otros objetos puedan reaccionar al cambio
de estado si es necesario.

 Conclusión

Las máquinas de estado ayudan a organizar y estructurar comportamientos complejos en un


juego. Con la implementación de una máquina de estado en Godot, los estudiantes
aprenderán a desarrollar personajes y objetos interactivos que responden de forma coherente
a diferentes condiciones y estímulos en el juego.
6. Interfaz de Usuario: Registro de Puntuación y
Configuraciones en el Juego de Naves Espaciales
La interfaz de usuario (UI) es esencial para cualquier videojuego, ya que permite a los
jugadores interactuar con el juego y obtener información sobre su progreso y
configuraciones. En este apartado, se cubrirán los conceptos clave para crear una UI
que incluya un sistema de puntuación con grabación de datos, configuración básica
de sonido (música, efectos y mute), y una pantalla de menú principal y de reinicio del
juego.
En este apartado, abordaremos los nodos de tipo Control en Godot, su importancia en
la creación de interfaces de usuario (UI), y cómo utilizar singletons para manejar
registros y gravaciones en el juego. Esta comprensión es esencial para diseñar
interfaces efectivas y gestionar datos persistentes, como puntuaciones y
configuraciones del jugador.

6.1. Tipos de Nodos Control


Los nodos de tipo Control son fundamentales en Godot para construir interfaces de
usuario. Estos nodos son específicamente diseñados para manejar la presentación y la
interacción con los elementos visuales. A continuación se detallan los nodos más
utilizados en esta categoría:

 Control: Este es el nodo base para todos los nodos de control. No se renderiza,
pero proporciona funcionalidades comunes, como el manejo de entrada y la
disposición de otros nodos.
 Button: Un botón interactivo que puede ser presionado por el usuario. Se
utiliza comúnmente para acciones como iniciar el juego o confirmar
selecciones.
 Label: Un nodo que muestra texto en la interfaz. Ideal para mostrar
información al jugador, como puntuaciones o mensajes.
 LineEdit: Un campo de entrada de texto donde el usuario puede escribir
información, como nombres de usuario o configuraciones.
 TextureRect: Muestra una textura en la interfaz. Se utiliza para mostrar
imágenes, fondos o iconos.
 ProgressBar: Representa visualmente el progreso de una acción, como la carga
de un nivel o la salud del jugador.
 Panel: Un contenedor que puede tener un fondo y organizar otros nodos de
control dentro de él.

6.2. Diferencias con Otros Nodos


Los nodos de tipo Control se diferencian de otros tipos de nodos, como Node o
Spatial, en su propósito y funcionalidad:

 Nodos de Tipo Node: Estos nodos son más generales y no tienen


funcionalidades específicas para la UI. Se utilizan para la lógica del juego, el
manejo de la escena y otras tareas no relacionadas con la interfaz.
 Nodos de Tipo Spatial: Estos nodos son utilizados en entornos 3D. Aunque
pueden contener nodos de control, su función principal es gestionar la
posición y el movimiento en un espacio tridimensional.
Los nodos de Control están diseñados para facilitar la creación de interfaces de usuario
interactivas, mientras que los otros nodos son más adecuados para la lógica del juego
y la manipulación de escenas.

6.3. Configuración Básica de Música y Efectos


Además de manejar registros, un singleton puede ser útil para gestionar la
configuración de música y efectos de sonido. Aquí hay un ejemplo de cómo
implementar controles de volumen:
gdscript

func set_music_volume(volume: float):


settings["music_volume"] = volume
# Actualiza el volumen de la música en el juego

func mute():
settings["is_muted"] = true
# Silencia la música y efectos

func unmute():
settings["is_muted"] = false
# Restaura el volumen anterior

6.4. Menú Principal y Reinicio del Juego


Finalmente, es esencial tener un menú principal y una opción para reiniciar el juego.
Puedes usar una Scene separada para el menú y cargarla cuando sea necesario:

 Menú Principal: Contendrá botones para comenzar el juego, acceder a


configuraciones y salir.
 Reinicio del Juego: En el script del juego, puedes crear una función que reinicie
el estado del juego, llame a la función de carga de puntuaciones y restablezca
las configuraciones:
gdscript

func restart_game():
get_tree().reload_current_scene() # Recarga la
escena actual
Global.load_scores() # Carga las puntuaciones

6.5. Registro de Puntuación y Guardado de Variables


En Godot, se pueden guardar los datos del jugador (como puntajes altos) en archivos
utilizando el sistema de archivos nativo. Esto permite que el puntaje o récord
permanezca guardado entre sesiones del juego.

 Creación del Registro de Puntuación: Crea una función para guardar y cargar
la puntuación en un archivo .save que registre el puntaje máximo (high
score).
gdscript

# Registro de puntuación en Godot


extends Node

var puntuacion_maxima = 0

func guardar_puntuacion(puntuacion):
if puntuacion > puntuacion_maxima:
puntuacion_maxima = puntuacion
var file =
FileAccess.open("user://record.save", FileAccess.WRITE)
file.store_line(str(puntuacion_maxima))
file.close()

func cargar_puntuacion():
var file = FileAccess.open("user://record.save",
FileAccess.READ)
if file:
puntuacion_maxima = int(file.get_line())
file.close()

o guardar_puntuacion(puntuacion): Actualiza y guarda la


puntuación máxima en el archivo si la nueva puntuación es mayor.
o cargar_puntuacion(): Lee el archivo de guardado para cargar la
puntuación máxima al inicio del juego.

 Mostrar Puntuación en la UI:

o Utiliza un Label en la interfaz de usuario para mostrar la puntuación


actual del jugador y la puntuación máxima cargada.

6.6. Configuración Básica de Sonido (Música, Efectos, y


Mute)
Crear una configuración de sonido para controlar la música y los efectos permite una
experiencia personalizada para el jugador. En Godot, se puede hacer esto mediante
nodos de audio y variables de configuración.

 Nodos de Audio:

o AudioStreamPlayer para música de fondo.


o AudioStreamPlayer o AudioStreamPlayer2D para efectos de sonido.
 Implementación del Control de Volumen y Mute:
gdscript

# Control de música y efectos


var musica_jugando = true
var efectos_jugando = true
onready var musica = $AudioStreamPlayer
onready var efectos = $AudioStreamPlayer2D

func cambiar_estado_musica():
musica_jugando = !musica_jugando
musica.volume_db = -80 if !musica_jugando else 0 #
-80dB para mute, 0 para volumen normal
func cambiar_estado_efectos():
efectos_jugando = !efectos_jugando
efectos.volume_db = -80 if !efectos_jugando else 0

o cambiar_estado_musica(): Alterna el estado de la música entre


activada y mute.
o cambiar_estado_efectos(): Alterna el estado de los efectos de
sonido.

 Botones de Configuración:

o Añade botones en el menú de opciones para activar o desactivar la


música y los efectos, asignándoles las funciones
cambiar_estado_musica y cambiar_estado_efectos.

6.7. Menú Principal y Reinicio del Juego


El menú principal y la pantalla de reinicio permiten al jugador navegar por las opciones
de juego, configuraciones y registros de puntuación.

 Menú Principal:

o Incluye opciones como “Iniciar Juego”, “Configuración”, y “Salir”.


o Configura este menú para que sea la primera pantalla que el jugador
vea al iniciar el juego.
gdscript

# Menú Principal
func iniciar_juego():
# Código para iniciar el juego, como cargar la
escena de juego principal

get_tree().change_scene("res://NivelPrincipal.tscn")

func ir_a_configuracion():
# Cambiar a una escena de configuración o mostrar
un menú de configuración
pass

func salir_del_juego():
get_tree().quit()

 Pantalla de Reinicio y Opciones:

o Al finalizar una partida, muestra la opción de “Reiniciar” o “Regresar al


Menú Principal”.
o Crea un menú en la pantalla de finalización del juego que permita al
jugador ver su puntuación actual y elegir si desea intentarlo
nuevamente o regresar al menú principal.

 Botones y Colores en la UI:

o Usa botones visibles y de fácil acceso para que el jugador pueda


seleccionar las opciones.
o Aplica colores y efectos para indicar el estado actual de la opción (por
ejemplo, verde para “Activado” y gris para “Desactivado” en las
opciones de sonido).
gdscript

# Menú de reinicio
func reiniciar_juego():
# Reinicia la partida actual
get_tree().reload_current_scene()

func regresar_menu_principal():
# Regresa al menú principal
get_tree().change_scene("res://MenuPrincipal.tscn")
7. Integración Final y Exportación del Juego de
Naves Espaciales
Este último módulo cubre la integración de todas las piezas del juego en un proyecto
cohesivo y profesional en Godot, seguido por el proceso de exportación para
diferentes plataformas. Aquí se desarrollan pasos para revisar el proyecto, optimizarlo
y finalmente configurarlo para su distribución, ya sea en escritorio, móvil o web.

7.1. Integración Final del Proyecto


La integración final implica consolidar los sistemas que se desarrollaron a lo largo del
curso: mecánicas de juego, interfaz de usuario, señales, sistema de puntuación,
configuración de sonido y menú. Los pasos incluyen:

 Revisión de Escenas y Nodos:

o Asegúrate de que cada escena funcione correctamente y que las


transiciones entre ellas sean fluidas (por ejemplo, del menú principal
al juego, y del juego a la pantalla de reinicio).
o Verifica que las interacciones entre los nodos (como los sistemas de
puntuación, eventos y UI) se realicen correctamente y de forma
predecible.

 Optimización de Recursos:

o Optimiza las texturas y sonidos: Comprueba que todas las imágenes y


sonidos tengan un tamaño adecuado para la plataforma de destino.
o Eliminar nodos innecesarios: Revisa las escenas y elimina cualquier
nodo o script que no se esté utilizando.
o Scripts: Limpia el código y elimina variables o funciones que no se
usen para mejorar el rendimiento.

 Revisión de Configuraciones de Juego:

o Prueba la configuración de la música y los efectos de sonido en


diferentes estados para asegurarte de que las opciones de volumen y
mute respondan correctamente.
o Verifica el sistema de registro de puntuación y la carga de datos,
asegurándote de que los datos persistan correctamente entre
sesiones.

 Polish y Ajustes Finales:

o Revisa la UI para que todos los elementos sean visibles y accesibles en


diferentes resoluciones.
o Ajusta colores, efectos de botones, y otros detalles visuales para
mejorar la presentación y hacer el juego más atractivo.
7.2. Exportación del Juego
Godot facilita la exportación a múltiples plataformas (escritorio, web y móvil), pero
cada una requiere configuraciones específicas. Aquí te explico cómo preparar el juego
para su exportación:

 Preparación de Configuración de Exportación:

o En Godot, ve a Project > Export y selecciona Add para agregar una


plataforma de destino.
o Configura los ajustes específicos de la plataforma, como el nombre del
paquete, la orientación de pantalla y las opciones de compresión de
recursos.

 Exportación para Plataformas Específicas:

o Exportación para Web (HTML5):


 Configura los ajustes de HTML5 en el menú de exportación.
Activa la opción de Compress para reducir el tamaño del
archivo y asegúrate de habilitar la compatibilidad con
WebAssembly.
 Esta opción permite que el juego se ejecute en navegadores,
siendo ideal para compartir el proyecto en línea.
o Exportación para Windows/Mac/Linux:
 En Export Options, configura el nombre del ejecutable y los
íconos.
 Define si el juego debe ejecutarse en modo ventana o pantalla
completa.
 Exporta a Windows (.exe), Mac (.app) o Linux (.x86_64), según
la plataforma que desees.
o Exportación para Android/iOS:
 Configura las opciones para Android e iOS, como el nombre
del paquete, la clave de firma (en Android), y permisos.
 Prueba el juego en el simulador o dispositivo real para verificar
el rendimiento y las características específicas de la plataforma
móvil.

 Pruebas Posteriores a la Exportación:

o Ejecuta el juego en cada plataforma exportada para asegurarte de que


funcione sin errores y que todos los sistemas (UI, puntuación, sonido,
etc.) se comporten como se espera.
o Revisa el rendimiento y ajusta detalles si es necesario, especialmente
para versiones móviles y web.

7.3. Empaquetado y Publicación del Juego


 Empaquetado:

o Una vez exportado, prepara un archivo comprimido (.zip) o ejecutable


para su distribución. Asegúrate de incluir todos los archivos
necesarios, como librerías adicionales o notas de instalación si es
necesario.

 Distribución y Publicación:

o Publica el juego en plataformas de distribución como Itch.io, (para


juegos de PC) o Google Play Store (para Android).
o Si es posible, agrega una página de descripción con capturas de
pantalla, detalles del juego, y un enlace a un repositorio o sitio web de
soporte.

También podría gustarte