Você está na página 1de 10

Godot Engine: Conheça os Nodes

William Tumeo

Novastrike Media, Desenvolvimento de Jogos, Brasil

RESUMO Quanto ao sistema de script, os desenvolvedores decidiram


“Conheça os Nodes” é um uma apresentação e tutorial organizada implementar uma linguagem que fosse muito mais simples que o
pelo grupo Novastrike Media focada em dar uma breve introdução C++. Eles chegaram a cogitar usar linguagens como Python ou
à Godot Engine, uma game engine livre e de código aberto que Lua, mas tiveram problemas relacionados à garbage-collector e
vem crescendo constantemente nos últimos anos. afins. Então, acabaram por criar uma linguagem de script própria,
A apresentação possui duas partes, a primeira parte consiste em que suportasse a arquitetura da engine, chamada de GDScript (ou
contar um pouco sobre a história da Godot Engine, suas filosofias Godot Script). O GDScript é uma linguagem simples muito
e seus objetivos. A segunda parte é o tutorial em si, focado em similar ao Python com algumas instruções específicas a mais.
introduzir várias das principais funcionalidades da engine. Além das instruções específicas voltadas ao desenvolvimento de
jogos, uma das vantagens do GDScript é que a linguagem é uma
Palavras-chave: SBGames, Tutoriais, Computação, Básico. abstração da API em C++ da engine, facilitando o entendimento
do núcleo da ferramenta caso o desenvolvedor queira lidar com
1 INTRODUÇÃO À GODOT ENGINE C++.
A segunda principal filosofia da Godot Engine é preservar os
paradigmas da orientação a objetos. A engine usa uma hierarquia
1.1 História de árvore e nodes, e cada node possui um tipo de comportamento.
A Godot Engine teve o seu início em 2001, como uma Alguns nodes podem compartilhar alguns comportamentos e dessa
ferramenta fechada escrita em C++, que era somente usada pelos forma pode haver um node pai que vai servir como classe base,
seus criadores, Juan Linietzky e Ariel Manzur do estúdio OKAM mantendo assim uma relação de herança comum na orientação a
(Argentina). O nome Godot está relacionado à peça de teatro objetos.
“Esperando Godot” de Samuel Beckett, onde dois personagens
estão todos os dias à espera de alguém chamado Godot, mas esse 1.3 Objetivos
alguém nunca chega. O nome era provisório, mas com o tempo O objetivo inicial dos criadores da Godot Engine foi
acabou permanecendo. disponibilizar uma ferramenta livre e gratuita que pudesse servir
A ferramenta continuou sendo melhorada para uso interno como uma alternativa às ferramentas pagas e proprietárias. Após 3
durante alguns anos, então decidiram lançá-la como um software anos de lançamento, os objetivos se expandiram com o
livre e de código aberto em 2014. Uma versão beta foi lançada em crescimento da comunidade e do suporte. Os objetivos agora são
janeiro e somente em dezembro do mesmo ano lançaram uma focados em tornar a engine tão boa quanto, ou até melhor que as
versão estável (1.0). ferramentas mais usadas comercialmente. Esse foi um dos
Após 2 anos de desenvolvimento, lançaram mais uma versão motivos pela adesão do C# como uma das linguagens suportadas
maior estável (2.0) com diversas melhorias. Depois do lançamento além do GDScript: atrair a atenção de vários usuários da engine
da versão 2.1, os desenvolvedores planejaram uma versão 2.2 com Unity3D.
aperfeiçoamentos na distribuição para HTML5 (por incentivo
financeiro da Mozilla), melhorias internas no motor gráfico, 2 COMPARATIVO
implementação da distribuição para UWP (Windows Store e
XONE), implementação de suporte a linguagem C#, entre outros É possível fazer um comparativo direto entre a Godot Engine e
aspectos. a engine mais usada atualmente, Unity3D.
Como a versão 2.2 traria muitas mudanças, o lançamento
2.1 Cenas e Prefabs
começou a ser adiado cada vez mais vezes. Os desenvolvedores,
então, acabaram decidindo cancelar a versão 2.2 e programar O sistema de cenas e prefabs das duas engines pode parecer
todas as novas funcionalidades para a versão 3.0. similar inicialmente, porém são totalmente diferentes. A Godot
Atualmente a engine possui duas linhas de desenvolvimento: a Engine possui um sistema de cenas e hierarquia similar: a cena é
principal, focada na versão 3.0, que está em alfa, e a linha de como um container de objetos em uma hierarquia de árvore.
suporte à 2.1, que ainda é amplamente usada e se encontra Porém em vez de ser uma árvore de GameObject (Unity), é uma
atualmente na versão 2.1.4. árvore de Nodes (nós).
Na Unity3D, os prefabs são objetos salvos como um arquivo
1.2 Filosofias para ser usado como um molde para outros objetos que
A principal filosofia da Godot Engine é a simplicidade. Essa compartilham algumas características. Na Godot Engine não
filosofia é aplicada em praticamente toda a ferramenta, desde existe o termo prefab, mas a ideia é parecida: você pode salvar
coisas relacionadas ao editor ao e script até coisas relacionadas ao algum Node ou ramo da sua cena como uma nova cena. Isso
núcleo da engine. significa que toda cena pode ser um “prefab” e qualquer cena
No editor, toda a organização é voltada para maximizar a pode ser usada como um molde e ser instanciada dentro de outras
usabilidade, mantendo a simplicidade sem perder a eficiência. Isso cenas.
torna muito mais fácil o acesso à ferramenta por artistas, músicos, A maior vantagem dessa estrutura é poder criar, atualizar e
game designers e animadores. estruturar os sistemas de “prefabs” com muito mais praticidade.
Figura 1: Sistema de cenas e prefabs na engine Unity3D. Figura 3: Sistema de scripts na engine Unity3D.

Figura 2: Sistema de cenas na Godot Engine. Figura 4: Sistema de herança e scripts na Godot Engine.

2.2 Objetos e Scripts 3 TUTORIAL


O sistema de objetos das duas engines é extremamente O tutorial consiste em um jogo de pong que será focado em
diferente. A engine Unity3D utiliza a arquitetura padrão de apresentar alguns dos principais recursos da arquitetura, do editor,
mercado, que é utilizar um objeto simples e vazio (GameObject) e do script, entre outros aspectos da engine.
a customização desse objeto é feita através de componentes, que
darão características e comportamentos diferentes para cada 3.1 Primeiros Passos
objeto.
A Godot Engine utiliza objetos com características e 3.1.1 Introdução ao Editor
comportamentos pré-montados, reutilizando características por O editor da Godot Engine é formado por algumas barras de
meio de herança, como normalmente se faz em programação ferramentas na posição superior e docks nas laterais. Os docks
orientada a objetos. contém a árvore da cena, arquivos do projeto, inspetor de objeto e
O sistema de scripts também é bem diferente. Na engine outras ferramentas do objeto selecionado. Os docks podem ser
Unity3D cada script é usado como um novo componente, sendo reposicionados nas laterais do editor.
possível adicionar vários scripts ao mesmo objeto. Já na Godot
Engine, um script é utilizado como uma nova classe que vai
herdar as características e comportamentos de uma outra classe.

Figura 5: Visão geral do editor.

É possível acessar as configurações do seu projeto na barra de


ferramentas “Scene > Project Settings”. Nesta tela aparecerá
várias configurações que já vêm por padrão, e é possível mudar o
que quiser. Todas as alterações serão gravadas no arquivo
“engine.cfg” que é gerado automaticamente quando um projeto dinamicamente tipadas, como na linguagem Python. Isso quer
novo é criado. dizer que não é preciso definir um tipo para as variáveis, apenas
usar a instrução “var” e um nome para a variável (usar a instrução
“const” para constantes). Seguindo abaixo temos a definição de
uma função (método) da classe. Os blocos são indentados, assim
como no Python, e a definição de função é parecida, só que em
vez de usar a instrução “def”, usa-se “func”.
A função que já veio definida, “_ready”, é uma função nativa
dos nodes que é executada sempre que um node está pronto. Isso
significa que ele já carregou todos os seus assets e os seus nodes
filhos (se houver algum) também já estão prontos.

Figura 6: Visão geral das configurações do projeto.

A princípio mudaremos apenas a resolução do jogo para um


tamanho menor e desativaremos filtros de textura e geração de
mipmaps pois os assets do jogo são em pixel art.
3.1.2 Primeira Cena
Agora vamos criar a primeira cena (por padrão o editor já abre
com uma cena vazia). Nesta cena vamos colocar toda a base do
jogo pong: a bola, os pads e o separador. Como essa cena
precisará renderizar várias coisas, é recomendável utilizar um
Node2D como raiz da nossa árvore (esse node pode ser Figura 8: Visão geral do editor de scripts.
renomeado para “pong”). Vamos começar definindo uma constante para a velocidade do
Vamos começar adicionando um dos pads como node movimento do pad e uma variável para armazenar o tamanho da
Sprite e então adicionar uma textura pelo inspector. Após fazer tela (será usada para limitar o movimento do pad no eixo Y).
isso, já pode salvar a cena, clicando em “Scene > Save Scene” ou A variável que guardará o tamanho da tela é de um tipo
usando o atalho do teclado “Ctrl+S”. A Godot Engine não possui primitivo da Godot Engine, o Vector2, que é utilizado para
um sistema de pastas padronizado para os assets, permitindo, vetores 2D (eixo X e Y). Por ser um tipo primitivo, ele sempre é
assim, que se crie a estrutura que achar melhor. Nesse caso passado como valor e não como referência, da mesma forma que
deixaremos as cenas e scripts na pasta “game”. os tipos String (str), int, float e bool. Para obter o tamanho da tela
basta usar um método que se encontra na classe estática “OS”.
Caso precise encontrar informações sobre a API da Godot Engine,
membros e métodos de várias classes, nodes e afins, há dentro do
editor de script uma referência das documentações totalmente
offline.

Figura 7: Adicionando uma textura ao node Sprite.

3.1.3 Introdução ao GDScript


Agora podemos adicionar um script a este node para poder
estendê-lo, clicando no botão de script na parte superior do dock
da árvore ou clicando com o botão direito do mouse no node. Figura 9: Visão geral da documentação offline.
Na tela que surgirá, selecione um caminho para o novo script
(usaremos o caminho “game/pad.gd”) e clique em Create. 3.1.4 Loop e Inputs
Automaticamente o editor de scripts será aberto com um script Agora faremos a movimentação do pad. Primeiro precisaremos
padrão como exemplo. de um método que seja executado a cada frame (um loop) para
Este script padrão possui algumas instruções bem básicas e logo capturar os inputs. Na Godot Engine, esse método é definido
no início vemos a instrução “extends Sprite”. Essa instrução como “_process(delta)”, sendo delta a diferença de tempo entre
indica que o seu script herdará tudo que estiver na classe Sprite. cada frame: aproximadamente 1/60 (1 segundo para cada 60
Mais abaixo temos alguns comentários explicando como criar frames). Um detalhe importante é que é necessário ativar esse
algumas variáveis para a classe. As variáveis no GDScript são
método antes que ele comece a funcionar a cada frame. Ele é Diferente das variáveis comuns que não precisam de um tipo
ativado ou desativado usando o método “set_process(bool)”. para serem definidas, as variáveis exportáveis precisam ser
Para poder capturar os inputs do jogador, seja via teclado, definidas usando um “hint”, que podem ser tipos primitivos ou
mouse, touch ou joystick, é preciso utilizar os métodos da classe qualquer tipo de objeto que herde da classe “Resource”. É
estática “Input”. Além de capturar inputs diretamente, é possível possível usar alguns “hints” especiais que servem para facilitar a
remapeá-los usando o Input Map nativo da Godot Engine, usabilidade no editor, como, por exemplo, exportar uma sequência
chamado de “action”. Cada action pode capturar vários tipos de de números inteiros (começando por zero) com nomes
inputs ao mesmo tempo. Já existem algumas actions definidas por previamente definidos, como se fosse um “enum”. Ou seja, no
padrão, que são utilizadas para navegar nas UIs. Por enquanto editor aparece uma lista com nomes (String), mas no script é uma
vamos usar as actions já definidas, “ui_up” e “ui_down”. sequência numérica.
Para checar se alguma ação está sendo pressionada, pode-se Vamos usar esse hint para exportar os números de 0 a 2 (sendo
usar o método “is_action_pressed(action)” da classe Input dentro 0 um “player” nulo). Depois de criar essa variável, vamos ter que
do método “_process”. Somente para testes, podemos usar a criar actions para cada player, up/down para o player 1 e up/down
função “print” para exibir qualquer string no console (debugger), para o player 2.
no caso, exibir algo sempre que as ações forem pressionadas. A
sintaxe para condicionais (if/else) é exatamente igual à da
linguagem Python.

Figura 10: Básico da checagem de inputs e loop. Figura 12: Criando input actions para cada player.

Para fazer o pad se mover, precisaremos atualizar a sua posição Agora precisamos fazer uma pequena modificação na checagem
levando em consideração a velocidade do movimento. Primeiro dos inputs. Em vez de usar “ui_up” e “ui_down”, vamos trocar
guardamos a posição atual do pad em uma variável utilizando o pelos nomes novos, porém, no lugar do número do player,
método “get_pos”, antes de capturar os inputs. Em cada usaremos um template de string simples, que nesse caso vai ser o
condicional dos inputs, deve-se adicionar ou subtrair no atributo termo “%s”. Por exemplo: “pad_up_%s”, e logo em seguida deve-
“y” dessa variável o produto da velocidade com o delta do se aplicar o template da mesma forma como é feito na linguagem
processo. No canvas 2D da Godot Engine, o eixo Y é contado de Python, utilizando a variável que guarda o número do player.
cima para baixo, ou seja, para ir para baixo, deve-se adicionar e
para ir para cima, deve-se subtrair. Após o bloco das condicionais,
é possível limitar o movimento utilizando a função matemática
“clamp(valor, mínimo, máximo)”, sendo o mínimo zero (topo de
tela) e o máximo a altura da tela, que é o atributo “y” (ou
“height”) do Vector2 da variável em que foi guardado o tamanho
da tela. Após isso, basta usar essa variável para chamar o método
“set_pos(position)”.

Figura 13: Exportando variáveis e formatando strings.

Voltando para o editor, já é possível alterar o player pelo


inspector do node.

Figura 11: Movimentando o pad no eixo Y.

3.1.5 Variáveis exportáveis


Agora que a movimentação já está funcionando, precisamos
duplicar isso para ter um segundo jogador. Há várias formas de se
fazer isso. A menos indicada seria duplicar o node “pad” e refazer
todo o script para alterar somente as actions do input. Para poder
reaproveitar o node e o script, é possível utilizar variáveis
exportáveis, que poderão ser acessadas pelo editor.
Figura 14: Selecionando o player da variável exportada. 3.1.7 Adicionando uma Bola
Seguindo os passos anteriores para o pad, adicione um novo
3.1.6 Duplicando e Salvando Nodes node Sprite, uma textura e um script para a bola. Para começar,
Isso já é o suficiente para poder duplicar o node (clique com o precisaremos de algumas variáveis importantes, como a
botão direito do mouse sobre o node > Duplicate), porém há um velocidade inicial da bola, um multiplicador de velocidade
problema. O node duplicado não vai compartilhar as mesmas (qualquer valor maior que 1), a velocidade atual da bola, a direção
características para sempre, somente o arquivo de script. Caso seja da bola (que vai ser um Vector2) e também o tamanho da tela
preciso mudar algumas coisas, como textura, posição inicial e o novamente.
mais importante, caso o node tenha algum filho ou seja necessário Para facilitar algumas coisas, vamos criar uma função que será
adicionar ou remover filhos, será necessário fazer isso para todas usada para resetar a posição, direção e a velocidade da bola
as cópias manualmente. quando ela sair da tela. Podemos usar um valor que pode ser “-1”
Para evitar esse tipo de situação, pode-se pensar nesse node ou “1” para o eixo X (direita ou esquerda) para a direção e a
“pad” como um prefab, e então pode-se salvá-lo como uma cena metade do tamanho da tela para a posição inicial.
nova. É possível fazer isso salvando o ramo inteiro (clique com o Depois disso, precisamos adicionar um loop (_process) para
direito sobre o node > Save Branch as Scene). fazer a movimentação, criar uma variável com a posição atual da
bola e logo em seguida adicionar a essa variável a direção atual
dela multiplicado pela velocidade e o delta. Lembrando que o
Vector2 pode realizar operações matemáticas com números
inteiros e flutuantes.
Mais abaixo é possível fazer uma checagem se a bola saiu da
tela pelas laterais, utilizando zero como a lateral esquerda e a
largura da tela como lateral esquerda. Se tiver saído pelas laterais,
deve-se resetar a bola. Senão, aplica-se o movimento.

Figura 15: Salvando um node ou um ramo como uma


nova cena.

Salvando este node como uma nova cena, será possível usá-lo
como origem de ambos player 1 e 2. Tudo que for adicionado
nessa cena será herdado por todas as instâncias dessa cena. Agora
já é possível duplicar esse node com segurança e configurar o
número do player para cada um dos nodes.
Para diferenciar visualmente os pads, pode-se alterar a Figura 17: Movimentação básica da bola.
propriedade “Modulate” de cada um deles. Isso mudará a cor dos
pads. 3.1.8 Interagindo com os pads
Até o momento, a disposição da árvore ficará da forma
mostrada na imagem abaixo. Lembrando que sempre que um node Para fazer a bola bater nos pads, vamos precisar interagir com
for uma instância de alguma cena, aparecerá um ícone de “cena” eles de duas formas. Primeiro, precisamos obter uma referência de
ao lado do nome. ambos os pads em array e precisamos saber o tamanho e a posição
deles. Para obter os pads, vamos utilizar um recurso que destaca
um node adicionando ele a um grupo, similar às tags da Unity3D.
É possível adicionar nodes em algum grupo pela aba Node no
editor. Vamos adicionar o node da cena pad ao grupo “pad”, assim
todas as instâncias também serão adicionadas.

Figura 16: Disposição atual da árvore da cena.

Figura 18: Adicionando um node a um grupo.


Agora podemos pegar todos os nodes da cena que estão nesse
grupo. O método que retorna todos os nodes em um grupo
(“get_nodes_in_group(name)”) fica no objeto que contém toda a
árvore atual e pode-se obter esse objeto usando o método
“get_tree()”.
Como só é possível lidar diretamente com a árvore depois que o
node estiver em estado “ready”, seria necessário criar uma
variável vazia e depois utilizar esse método dentro da função
“_ready”. Para contornar esse tipo de situação, existe o comando Figura 20: Visão geral da linha do tempo do animador.
“onready”, o qual pode ser usado para variáveis que só serão
Um exemplo simples de uso seria adicionar um
instanciadas depois que o node estiver pronto.
AnimationPlayer na bola e colocar uma animação para rotacionar
3.1.9 Checando a colisão dos pads a bola em loop. Detalhe que, no editor, a rotação é passada em
graus e no código o padrão é radianos. Outro detalhe importante é
Para checar se a bola está colidindo com os pads, vamos utilizar
que a timeline usa tempo em segundos e não em frames.
uma checagem simples usando o tipo primitivo da Godot Engine
Para adicionar uma keyframe, basta deixar o animador aberto
Rect2, que é utilizado para guardar dois Vector2, um para posição
que ícones de chave serão visíveis em todas as propriedades do
e outro para tamanho.
node selecionado.
Dentro do loop, após atualizar a possível posição da bola, deve-
se fazer um loop “for” (que funciona de uma forma muito
parecida com Python) usando o array dos pads. Para cada pad,
deve-se gerar um novo Rect2 para ajustar a posição e a âncora do
pad, que por padrão fica no centro dele. Então, pode-se checar se a
posição da bola se encontra dentro deste Rect2 e se a bola está
indo em direção a esse pad (e não indo contra). Se essa checagem
for verdadeira, então é possível inverter a direção da bola para que
ela possa ir para o lado oposto.
Agora, a bola bate nos pads porém ela foge por cima e por
baixo. Para consertar isso é só checar previamente se a posição do
eixo Y é menor que zero ou maior que a altura da tela (e checar se
está indo na mesma direção), e então inverter a direção do eixo Y.

Figura 21: Adicionando um keyframe.

Pode-se alterar o tipo de interpolação da animação, assim ela


pode ir de 0° a 360° de forma contínua.
3.2.2 SamplePlayer e SamplePlayer2D
Ainda na bola, podemos adicionar um efeito sonoro sempre que
ela bater em algo. Para isso, podemos usar o node SamplePlayer,
que serve para tocar samples (wav). Porém, além do
SamplePlayer, há também o node SamplePlayer2D, que faz o
mesmo que o SamplePlayer mas considera a posição do som em
relação à câmera.
Figura 19: Limitando a movimentação da bola. Para utilizar um sample, precisamos adicioná-lo a uma
Se tudo correr bem, a base do jogo já funcionará como biblioteca de samples (SampleLibrary), que é basicamente uma
esperado. Porém sem nenhuma contagem de pontos ou algo do lista de samples que se pode salvar para reutilizar depois em
gênero, por enquanto. outros SamplePlayers.
Para tocar o som no script da bola, é preciso pegar uma
3.2 Conhecendo outros Nodes referência para o node filho SamplePlayer2D. Como a arquitetura
é de uma árvore, acha-se um node pelo seu caminho, levemente
Antes de fazer a checagem dos pontos e afins, vamos dar uma
parecido com o DOM em JavaScript. O método utilizado para
olhada em alguns outros nodes que também são importantes além
fazer isso é o “get_node(path)”.
do Node2D e Sprite.
3.2.1 AnimationPlayer
Começando com o node AnimationPlayer, que é um dos
melhores recursos da Godot Engine. Ele serve para animar todos
os outros nodes da árvore, utilizando uma linha do tempo Figura 22: Obtendo nodes na cena e tocando o efeito
(timeline). As animações são formadas por “keyframes”, que sonoro.
podem ser qualquer propriedade do node, como por exemplo:
posição, rotação, opacidade, etc. É possível também animar 3.2.3 Particles2D
transformações, caso esteja lidando com 3D e ainda chamar uma O node Particles2D é usado para gerar as partículas no canvas
função do node diretamente pela animação. 2D. Mesmo sendo simples, ele possui várias opções de
customização, como por exemplo: textura, tamanho, quantidade,
direção, gravidade e também máscaras.
Neste caso, usaremos este node para gerar um simples rastro no
movimento da bola. Para utilizar a gravidade em relação a bola, é
preciso antes desativar a propriedade “Local Space” do node, que
é usado para quando se vai gerar a movimentação da gravidade
manualmente, o que não acontece aqui.

3.3 Pontuação e Interface Gráfica


Figura 25: Emitindo sinais no script.
3.3.1 Sinais
Agora podemos voltar à questão da pontuação do jogo, mas Depois de criar e emitir o sinal, precisaremos conectar o sinal
antes de fazer o sistema de pontuação em si, temos que definir em alguma função, que será executada quando o sinal for emitido,
como saber quem ganhou a partida atual. Para fazer isso, similar ao event handler no JavaScript.
usaremos o sistema de sinais (signals) que é indicado pela Godot É possível conectar um sinal de duas formas. A primeira é
Engine. utilizando o método “connect(name, object, method)”, sendo
O sistema de sinais é basicamente um sistema de eventos object uma referência para o objeto dono do “method”, indicado
parecido com os eventos do DOM no JavaScript, a diferença é que numa string com o nome do método. Nesse caso, usaremos o
pode-se criar os sinais que quiser, além de usar os sinais nativos script para conectar o sinal ao próprio node.
de cada node. A outra forma é utilizando o próprio editor. Na aba “Node”, que
Como a bola já está checando quando ela sai da tela, vamos fica ao lado do inspector, estará uma lista de sinais que aquele
criar um sinal para avisar exatamente quando ela sair da tela, além node possui. Seria necessário apenas clicar em um sinal e então
de enviar uma informação nesse sinal, qual lado da tela a bola clicar em connect logo abaixo. Assim, pode-se escolher um node
estava quando saiu. da árvore que será a referência e digitar o nome do método. Essa
forma de conectar os sinais é muito útil, principalmente porque
não precisa necessariamente de um script.

Figura 23: Adicionando um signal no script.

3.3.2 Enums
Para facilitar a leitura do código, criaremos algumas variáveis
que contenham apenas números inteiros para indicar direções (up,
down, left, right). Em vez de utilizar uma variável ou constante,
podemos usar enums (constantes otimizadas para guardar somente
números inteiros e também utilizáveis sem valor específico), que
iria gerar uma sequência numérica começando em zero (ou Figura 26: Lista de sinais acessíveis pelo editor.
qualquer outro número definido no primeiro enum).
Vamos utilizar esses enums para o sinal da bola saindo da tela.
3.3.4 Singletons
Depois de criar o sinal na bola, vamos criar um script no node
raíz da árvore, que vai ser usado para conectar o sinal e checar
quem foi o ganhador da partida. Para facilitar a estrutura do jogo,
deixaremos o script da pontuação para outro tipo de node, o
singleton.
Singletons são cenas, ou somente scripts, que se carregam
durante o load inicial do projeto e se mantém ativos e acessíveis
globalmente. Não é preciso saber o caminho deste tipo de node
para acessá-lo, apenas saber seu nome global. Basta criar uma
cena qualquer (chamaremos de Score) com um node qualquer na
raíz e um script nela. Então só é preciso adicionar esta cena à lista
de singletons na aba “AutoLoad” das configurações do projeto. É
Figura 24: Adicionando enums ao script. possível escolher um nome global para o singleton, desde que não
conflite com outros termos nativos da engine.
3.3.3 Conectando e Emitindo Sinais No script de score adicionaremos duas variáveis para score
(uma para cada player), uma função que será utilizada para
Qualquer sinal é emitido utilizando o método incrementar o score e um sinal que será emitido sempre que o
“emit_signal(name, *args)”, sendo que a quantidade de score for atualizado, avisando qual player teve o score atualizado
argumentos vai depender do sinal. Nesse caso será somente um e o valor desse score.
argumento, o lado da tela. Esse sinal é muito importante pois torna o acesso ao score
muito mais fácil. Qualquer cena ou node poderia saber facilmente
quando o score é atualizado sem realmente depender do jogo em isso será irrelevante para a performance, podemos utilizar a fonte
si. dinâmica mesmo.
Podemos então criar duas labels (um para cada player), mudar o
texto para zero (sem score) e posicionar sobre a tela. Como o
score será atualizado pelo singleton Score, é possível criar um
script na raíz da cena para poder conectar o sinal de atualização de
score.
Para atualizar o texto das labels, vamos criar dois sinais no
script: um para quando o score do player 1 for atualizado e outro
para o player 2. Deve-se emitir o sinal convertendo o valor do
score para string pois o node Label aceita somente string e não faz
conversão automática.

Figura 27: Script do singleton para gerenciar o score.

Depois de criar o singleton, volte ao script principal na cena


pong e atualize o score de acordo com o lado da tela que a bola
saiu. Com isso, o score já funcionará perfeitamente, faltando
somente lidar com a interface gráfica.

Figura 29: Criando sinais para interagir com a interface.

Como foi citado, nem sempre é preciso criar um script para se


conectar um sinal, nesse caso podemos conectar esses sinais
diretamente à função que atualiza o text da label, que no caso é a
função “set_text”.

Figura 28: Atualizando o score dos players usando o


singleton.

3.3.5 Interface Gráfica


Para fazer a interface gráfica do jogo vamos criar outra cena,
que será a cena principal de fato. Na raiz, pode-se apenas deixar
um node simples pois não será necessário lidar com
transformações e afins. Então instancia-se a cena pong neste node. Figura 30: Conectando os sinais nas labels da interface.
Depois, será preciso criar uma camada para a interface gráfica,
que pode ser feita utilizando o node CanvasLayer. Este node é Após conectar os sinais nas duas labels, a interface gráfica já
como uma divisão da viewport, ele vai garantir que o funcionará como esperado. Lembrando que usar os sinais dessa
posicionamento da interface seja independente do forma é só uma das várias formas de se interagir com a interface
posicionamentoo do jogo, para evitar conflitos entre câmeras e gráfica, a organização pode variar muito de pessoa para pessoa e
problemas relacionados. também pelo contexto que os nodes estarão.
Dentro desse node, podemos adicionar qualquer tipo de node
relacionado à interface gráfica, que na Godot Engine são 3.4 Últimos Detalhes
chamados de Control Nodes. Esses Control Nodes são todos os
nodes que herdam do node Control, que tem a mesma origem dos 3.4.1 Node StreamPlayer
Node2D, a classe CanvasItem. Para deixar o jogo mais agradável, adicionaremos uma música
Como esta interface será somente para os valores do score, simples em loop. Em vez de utilizar o node SamplePlayer, vamos
usaremos somente o node Label, que serve para exibir textos usar o node StreamPlayer, que é indicado para streams, como, por
simples. exemplo, uma música no formato OGG. Uma stream pode conter
É possível utilizar arquivos de fontes comuns (ttf ou otf) de um loop ou não, e quando tiver, é possível definir um tempo
duas formas, dinâmica e estática. A fonte dinâmica é rasterizada preciso para o reinício do loop, caso não seja exatamente no
durante a execução do jogo e a fonte estática é importada e começo da stream.
rasterizada previamente, gerando um arquivo de textura. A fonte
dinâmica é muito mais prática porém consome mais
processamento pelo carregamento dinâmico. Como no nosso caso
3.4.2 Pausando o Jogo
É possível criar um sistema de pause bem simples
utilizando os estados de pause contidos nas propriedades de todos
os nodes. Esses estados são considerados sempre que o pause é
ativado. Se o estado for “stop”, aquele node específico terá seu
processamento parado; se o estado for “process”, o pause será
ignorado por completo e o node continuará processando; e se o
estado for “inherit”, o estado será herdado do node pai. Por padrão
o estado dos nodes é “inherit” e o node raiz tem o estado “stop”
como padrão.
Para ativar ou desativar o pause, basta utilizar o método
“set_pause(bool)” que fica no objeto da árvore atual (acessado
pelo método “get_tree()”).
Esse método pode ser usado facilmente em uma função que
checa o input de alguma action para o pause. Lembrando que o
script responsável por desativar o pause precisa ter o estado
“process”.

4 CONCLUSÃO
Após a conclusão do tutorial, teremos um pequeno jogo que,
apesar de simples, já possui várias funcionalidades importantes
que em outras engines e frameworks podem ser consideradas
muito mais difíceis de se implementar, como por exemplo,
animações e interface gráfica do usuário.
Este tutorial mostra por que e como a Godot Engine está se
tornando uma opção viável além das engines mais usadas
atualmente, como Unity3D e Unreal Engine. Mesmo que a versão
2.1 não tenha um suporte ostensivo para o desenvolvimento 3D,
ainda vemos vários usuários utilizando a Godot Engine para esse
fim, com o foco em dispositivos que possuem um hardware
considerado fraco, já que a versão 2.1 utiliza GLES2 (OpenGL
ES2) como driver de vídeo, que é acessível para vários tipos de
hardware.
O próximo lançamento da Godot Engine (versão 3) dará vários
passos a frente para melhorar o suporte 3D da engine,
implementando o driver GLES3 e vários outros recursos focados
no desenvolvimento de jogos 3D.

REFERÊNCIAS
[1] VERSCHELDE, Rémi. FIRST PUBLIC RELEASE. Disponível em
<https://godotengine.org/article/first-public-release>.
[2] VERSCHELDE, Rémi. GODOT HISTORY IN IMAGES.
Disponível em <https://godotengine.org/article/godot-history-
images>.
[3] LINIETSKY, Juan. MORE PROGRAMMING LANGUAGES IN
GODOT, WANT TO HELP. Disponível em
<https://godotengine.org/article/godot-getting-more-languages>.

Você também pode gostar