Tutorial para facer o teu primeiro xogo en Godot... en galego!
Qué é Godot?
Godot é un motor de videoxogos. É dicir, é un programa co que podemos desenvolver videoxogos, que poden ser en 2D e 3D. Ademais, estes videoxogos poden ser tanto para Windows, Android, web, Linux... porque é un motor multiplataforma.
Integra un editor dotado con ferramentas para cubrir as necesidades máis comúns na edicións de xogos.
Creouse en Bos Aires por Ariel Manzur e Juan Linietsky, pero como a súa licencia é libre, agora a batuta a leva a propia comunidade. Tamén está a Godot Foundation, quen financia iniciativas e actividades orientadas á mellora do motor e a súa difusión.
Dito isto, é hora de descargalo e poñerse a fedellar!
Descargando Godot
Entra en https://godotengine.org/ e dalle a descargar (Download). Podes elixir unha versión para Windows ou para outras plataformas (baixa pola páxina ata acadar unha lista chamada “Supported platforms”).
Para comezar, sempre recomendo a versión máis actualizada e a que non ten soporte para C# (imos a programar todo en GDScript, unha linguaxe de programación para a que foi pensada Godot).
Descomprime o ficheiro descargado e xa podes empregar Godot, non ten unha instalación máis aló que iso e tampouco é preciso crearse ningunha conta de usuario en ningures.
Coma recomendación, crea un cartafol nun sitio accesible e de fácil consulta e non deixes o programa onde Descargas.
Creando o teu primer proxecto
No meu caso, a descarga do programa a fixen para Windows. Os ficheiros que se descargan de Godot son dous, diferéncianse entre si que un ten a consola visible con liñas de comando (exemplo: Godot_v4.2.2-stable_win64_console.exe) e a outra non. A efectos prácticos para este tutorial, non nos afecta en absoluto. A "_console.exe" executa tamén o motor, mais ofrece una ventana con visor de liñas de comando que permiten visualizar tódolos outputs.
Ao executar o .exe elixido, ábrese o Administrador de Proxectos, onde estarán os accesos aos xogos que estamos a desenvolver. Dende aquí tamén pódese cambiar o idioma de Godot (parte superior dereita). Para este tutorial tomarase o idioma castelán como referencia.
A continuación, podemos crear un novo proxecto no botón “+Nuevo” (novo). Escollemos un nome e un cartafol onde se gardarán todos os ficheiros do proxecto. Ata máis adiante non se recomenda tocar ningunha das opcións dispoñibles.
Tras crealo, ábrese por fin o motor e podemos comezar. Na parte esquerda, temos o menu escena e debaixo os recursos empregados no proxecto. Na parte central temos o espazo de traballo en la parte dereita temos o inspector.
- En vermello está o menú principal. Podemos gardar os progresos que fagamos dende Archivo, cambiar a configuración do proxecto dende "Proyecto" (proxecto) e outras opcións.
- En amarelo está a vista da escena. En Godot os xogos divídense en bloques, unhas unidades chamadas nodos, con funcionalidades concretas. O conxunto de nodos forman unha escena. Os nodos son como os ingredientes dunha receita. Hai ducias de tipos que poden, dende mostrar unha imaxe, a reproducir un son ou representar unha cámara.
- En marrón está a vista do Sistema de Archivos. Son todas as imaxes, sons e elementos en xeral que imos empregar no noso xogo. Estarán no cartafol do proxecto.
- En violeta está a vista principal ou o panel de traballo. Visualizarase aquí os elementos da escena na que se traballa.
- En verde está o Inspector coas as propiedades do elemento que estamos a manipular. Dende inspector pódese cambiar o aspecto dos sprites, cambiar as súas colisións por capas... e tamén podemos consultar as "sinais" dun nodo (veremos máis adiante qué son).
- En rosa está o selector de modos de traballo, podemos trabajar en 2D, 3D, Script e acceder á librería de assets (complementos ou elementos para engadir ao noso proxecto e que foron feitos por outras persoas que os comparten libremente).
Nós traballaremos en 2D para este tutorial, así que pulsamos onde "2D" na parte superior do motor.
Obxectivos do tutorial
O obxectivo do tutorial a partires de aquí é o desenvolvemento dun xogo 2D moi sinxelo co seguinte concepto: o protagonista é o peixe Rafa que crece a medida que se alimenta de algas.
Faremos uso como recursos o pack “Fish Pack” feito polo creador Kenney, que permite o seu uso de forma totalmente libre. https://kenney.nl/assets/fish-pack
De forma máis concreta, empregarase os .png do cartafol PNG > Retina: fishTile_001 (o fondo mariño), fishTile_032 (a alga) e fishTile_079 (o peixe).
Copiaremos esos ficheiros nun cartafol dentro do noso proxecto, por exemplo, co nome Sprites.
Creando a alga e o peixe
Imos crear a primeira escena para o proxecto: o peixe. A continuación faremos a alga.
Tanto o peixe como a alga van a estar formados por tres nodos, un nodo pai de area, no que definimos os elementos como un área delimitada do espacio. O segundo nodo, o primeiro fillo, é o do seu sprite (a parte visual) e, por último, temos a área de colisión, onde definiremos unha área de interacción. Desta forma delimitaremos estos dous elementos que formarán parte do noso xogo.
Según o proxecto e o que precisemos nel, poderíamos partir dun diferente nodo para o peixe Rafa (e a alga). Escollín un nodo de Area2D como nodo pai para determinar unha zona do espacio en 2D, nese espacio pódese detectar outros nodos con colisión superpuestos (CollisionObject2D), entrando e saíndo. O uso máis común é para detectar contactos e superposición, sen existir unha colisión física, só un área que notifique o contacto.
A continuación, creamos un nodo “Sprite2D” e dende a vista do Inspector, poñemos a imaxe do fishTile_079 como textura e imos a reducir o tamaño a 0.3 dende Transform (no propio menú Inspector).
Tamén darémoslle forma de cápsula á área de colisión do peixe dun nodo de CollisionObject2D(podemos seleccionar outras formas para que a área de colisión sexa cadrada ou circular).Se escollemos como área de colisión unha con forma de cápsula dende shape, temos que rotala 90 grados en transform para poder traballar mellor con ela e englobar adecuadamente o peixe.
Diferencias entre Area2D, RigidBody2D e CharacterBody2D
Para este proxecto fixen uso de Area2D para delimitar no espacio o peixe e a alga, mais hai outros nodos que poden ser relevantes para facer proxectos.
Por unha parte, temos o nodo RigidBody2D que é un corpo físico que Godot lle provee física simulada. Non temos control sobre RigidBody2D directamente, senón que se lle aplican forzas (como a gravedade ou un impulso) e o motor de físicas de Godot calculará o movemento resultante, incluindo colisións, rebotes, rotacións, etc.
Por outra parte, temos CharacterBody2D, unha clase especializada para corpos con físicas que deben ser controlados polo usuario. Moi útil cando queremos mover un corpo de formas específicas con colisións co mundo, como no caso de personaxes manexados polo usuario.
Agora é momento de crear as algas que Rafa vai comer. A alga é soamente un Area2D interactiva que terá un sprite (a escala 0.5) e unha área de colisión en forma rectangular.
Garda as escenas do proxecto (alga e peixe) e teremos dúas escenas para empregar no proxecto, veremos cómo cando fagamos o escenario.
É unha boa costume gardar elementos iguais nun mesmo cartafol do noso proxecto. De igual forma que pusimos os sprites nun mesmo catafol. Así que podemos ter un cartafol de Escenas e gardar alí o peixe, a alga e o escenario.
Creando o escenario
Creamos unha nova escena co escenario. De igual forma cos anteriores elementos, imos darlle imaxe. Creo un novo nodo de Sprite2D e engádolle a imaxe da area e a estiro e adapto ao tamaño do recuadro que aparece no espazo de traballo. A continuación, arrastramos a escena de alga e o peixe dende Sistema de Archivos ao árbore da actual escena.
No caso no que o fondo quede por riba do resto de elementos, cambiaremos o orden de capas dende o inspector (en Ordering > z-index e lle damos ao Sprite2D do escenario o valor -1).
Agora podemos gardar a escena co nome que se queira (escenario, nivel_1...) e podemos executar o xogo no botón de play na parte superior dereita de Godot. O programa preguntará se queremos facer da escena actual (o escenario) como escena principal e responderemos afirmativamente.
O xogo execútase, pero Rafa non se move. Porque non o programamos para que o fixera.
Configurando os controis
Para configurar os principais controis do peixe Rafa imos a "Proyecto > Configuración do Proyecto > Mapa de Entrada" e engadimos as teclas coas que queremos que se controle o peixe. Para iso crearemos primeiro as accións e despois asignaremos as teclas.
Toca programar: Que é GDScript? nocións elementais
É totalmente necesario saber programar para facer un xogo en Godot? Si. Por iso é necesario repasar o máis básico desta linguaxe de programación.
GDScript é unha linguaxe de programación de alto nivel e orientado a obxectos creado para Godot e a súa sintaxe está baseada en sangría, de forma similar a Python.
Pola túa conta podes realizar o tutorial de https://gdquest.github.io/learn-gdscript/?ref=godot-docs.
Existen tamén follas de referencia co máis elemental de GDScript como esta (en inglés) ou esta (en castelán).
Definirase a continuación o que imos a empregar no proxecto:
- Variables: son unha unidade de datos que pode cambiar de valor e almacenarse. Neste caso, gardaremos nunha variable chamada "speed" a velocidade do peixe Rafa e na variable "escala" o tamaño que ten o peixe Rafa. A velocidade do peixe é fixa no xogo, pero o valor da escala irase modificando a medida co peixe coma.
- Funcións: son fragmentos de código que poden ser infocados para a súa execución. Imos empregar funcións que ten Godot por defecto, non imos crear funcións novas.
- Estructuras condicionais con If: Estructura no que se evalúa unha condición e executa un bloque de código no caso no que se cumpla a condición. Por exemplo, o peixe móvese á dereita ao pulsarse a tecla dereita (condición), cando a pulsamos, cúmplese a condición, polo que o peixe se move.
Con respecto a funcións, teremos que prestar atención a:
- _process: procese que se require para cada frame, polo que é ideal para calqueira cosa que deba actualizarse en cada frame pero que non afecte ao xogo como tal (por exemplo, animacións, movementos de cámara...).
- _physics_process(delta): a diferencia que a anterior, emprégase para calqueira cousa que dependa da física do xogo, coma o movemento do personaxe.
- _on_area_2d_area_entered(area): crearemos unha función que detecte cando o peixe colisione coa alga (crecerá de tamaño) e cando a alga colisione co peixe (desaparece).
- scale.x e scale.y: a escala que se lle aplicará ao elemento (relativa ou absoluta) no eixe "x" ou no eixe "y", respectivamente. Non teremos que creala no proxecto, senón que xa está implementada no motor.
- position.x e position.y: a posición que se lle impondrá ao elemento (relativa ou absoluta). En x, un valor positivo é ir á dereita e en y, o valor positivo é hacia abaixo. Non teremos que creala no proxecto, senón que xa está implementada no motor.
- .flip_h: empregaremos a posibilidad de rotar no eixo horizontal o peixe para que se mova según o lado hacia o que se está a mover, ten dous valores posibles. No caso de que sexa true, rótase, pero se lle damos o valor de false, non o fará.
Con respecto a condiciones, teremos que prestar atención a:
- Input.is_action_pressed("nome do acción (abaixo, arriba..."): de pulsar os controis dunha acción de entrada ou input. Por exemplo, que ao pulsar arriba o peixe poda ir arriba.
Programamos o movemento do peixe Rafa
Abrimos a escena do peixe para que apareza no espazo de traballo, seleccionamos o nodo principal, e no menú Inspector (a parte máis abaixo) creamos un novo script e podemos abrilo para programar o movemento do peixe.
En primeiro lugar, creamos a variable "speed" (velocidade) co valor 200. O valor de 200 é un exemplo, podería ser outro valor. A maior valor, maior velocidade do peixe.
Temos que empregar unha función que detecte a tecla pulsada e faga mover o pez. Creamos a función _physics_process que depende do tempo (delta). Creamos un condicional no que según a tecla pulsada, cambia a posición x ou y do peixe (if Input.is_action_pressed("accion")). Engadimos tamén que o pez xire se pulsamos a esqueda con flip_h.
Creamos as condicións para saber qué fai o peixe según a tecla pulsada, neste caso, o seu movemento. Faremos uso de position.x e position.y e a posición que alcanza o peixe depende do tempo no que se pulsa a tecla (delta) e a velocidade do peixe (speed). A posición é relativa, non absoluta, polo que sumarase ou restarase un valor.
Para seleccionar a qué nodo lle afecta cada función, os temos que arrastrar dende o menú Escena e levar ao código. Aparecerá no código como $Area2D se aplicamos algo que afecte sobre ese área, se queremos que afecte ao sprite, arrastramos o sprite ao código e aparecerá como $Area2D/Sprite2D. Se afecta ao nodo principal, aparece como $".".
O código terá o seguinte aspecto:
extends Node2D var speed = 200 # Velocidade do pez var escala = 1 # A escala inicial do peixe, o 0.3 co que empeza func _physics_process(delta): $".".scale.x=escala # Cambia a escala a medida que o peixe come $".".scale.y=escala if Input.is_action_pressed("Abaixo"): position.y += speed*delta if Input.is_action_pressed("Arriba"): position.y -= speed*delta if Input.is_action_pressed("Esquerda"): position.x -= speed*delta $Area2D/Sprite2D.flip_h = true # Xira o sprite if Input.is_action_pressed("Dereita"): position.x += speed*delta $Area2D/Sprite2D.flip_h = false # Non xira o sprite
Programamos a alga
Agora temos que programar a alga, de tal forma que cando o peixe toque ou colisione cunha delas, esta desaparezca. Así que abrimos a escena da alga e engadímoslle un script.
Neste caso temos que facer uso dunha sinal. Unha sinal é un mensaxe que emite os nodos cando lles sucede algo específico, neste caso, necesitamos saber cando o peixe entra no área de colisión da alga. De tal forma, que cando suceda, se execute o código da desaparición da alga.
Mentres temos seleccionado a Area2D, imos a onde está o menú Inspector, pero seleccionamos “Nodos” e buscamos _on_area_2d_body_entered(body) e a conectamos coa alga. A nivel de código, empregamos o comando queue_free() para a desaparición da alga.
O código terá o seguinte aspecto:
extends Node2D func _on_area_2d_area_entered(area): queue_free() # Desaparece a alga
Programamos que Rafa medre a medida que come
Temos que crear unha sinal para que Rafa reaccione cando entre nun área (da alga) e simplemente engadimos dúas liñas ao código inicial de Rafa:
func _on_area_2d_area_entered(area): escala +=0.5
Límites da pantalla
Esta parte é un engadido final para facer que o peixe non poda sair do área delimitada do escenario. Faremos uso de diferentes funcións novas:
- _ready(): execútase os cálculos, funcións, estructuras... desta función inmediatamente ao chamar ao código ao que pertence. É o primeiro a executar.
- _physics_process(delta): a diferencia que a anterior, emprégase para calqueira cousa que dependa da física do xogo, coma o movemento do personaxe.
Creamos unha variable onde vaise gardar o tamaño da ventana e nel gardarase o valor da mesa, calculada pola variable get_viewport_rect().size que vaise a executar ao inicio do xogo (por iso emprégase a función _ready).
extends Node2D var speed = 200 # Velocidade do peixe var escala = 1 # A escala inicial do peixe var screensize # Tamaño da pantalla func _physics_process(delta): $".".scale.x=escala # Cambia a escala a medida que o peixe come $".".scale.y=escala if Input.is_action_pressed("Abaixo"): position.y += speed*delta if Input.is_action_pressed("Arriba"): position.y -= speed*delta if Input.is_action_pressed("Esquerda"): position.x -= speed*delta $Area2D/Sprite2D.flip_h = true # Xira o sprite if Input.is_action_pressed("Dereita"): position.x += speed*delta $Area2D/Sprite2D.flip_h = false # Non xira o sprite func _ready(): screensize = get_viewport_rect().size # Mide o tamaño da ventana pass func _process(delta): # Para que no salga da pantalla position.x = clamp(position.x, 0, screensize.x) position.y = clamp(position.y, 0, screensize.y) func _on_area_2d_area_entered(area): escala +=0.5
Despedida
Este é o meu primer tutorial orientado a creación de videoxogos. Tamén é o primeiro tutorial que fago en galego, así que haberá erros tanto no idioma como no tutorial en sí (faltan explicacións, especialmente relacionadas co GDScript), mais espero mellorar o tutorial para cando teña que dar o taller na quedada gogoteira de xullo que se celebra na Coruña. Gracias por ler este documento.