O Godot Engine está se desenvolvendo muito rapidamente e conquistando os corações dos desenvolvedores de jogos de todo o mundo. Talvez essa seja a ferramenta mais amigável e fácil de aprender para criar jogos e, para garantir isso, tente criar um pequeno jogo 2D. Para uma boa compreensão do processo de desenvolvimento de jogos, você deve começar com jogos em 2D - isso reduzirá o limite para entrar em um sistema de jogos mais sério. Embora a transição para o 3D por si só não seja tão difícil quanto possa parecer, afinal, a maioria das funções no Godot Engine pode ser usada com sucesso em 2D e 3D.
1. Introdução
A coisa mais simples que você pode pensar é em um jogo em que nosso personagem principal coletará moedas. Para complicar um pouco, adicione um obstáculo e tempo, como fator limitante. O jogo terá três cenas: Player
, Coin
e HUD
(este artigo não é considerado), que serão combinados em uma cena Main
.

Configurações do projeto
Antes de você começar a escrever scripts (scripts), que representam aproximadamente 80-90% do tempo total gasto na criação do jogo, a primeira coisa a fazer é configurar nosso projeto futuro. Em projetos grandes, é útil criar pastas separadas para armazenar scripts, cenas, imagens e sons, e devemos definitivamente levar isso em conta, porque quem sabe qual será o resultado final.
Quero fazer uma reserva imediata de que este artigo implica que você está um pouco familiarizado com o Godot Engine e que possui algum conhecimento e habilidades para usar essa ferramenta, embora eu me concentre no fato de que você está encontrando o Godot Engine pela primeira vez, ainda estou Aconselho que você primeiro se familiarize com o componente básico do mecanismo, estude a sintaxe do GDScript e entenda a terminologia usada (nós, cenas, sinais, etc.) e só então volte aqui e continue seu conhecido.
No menu do programa, vá para Project -> Project Settings
.
Outra pequena digressão. Eu sempre darei exemplos com base no fato de o usuário final usar a interface em inglês do mecanismo, apesar de o "Godot Engine" ter suporte para o idioma russo. Isso é feito para se livrar de possíveis mal-entendidos ou constrangimentos associados à tradução incorreta / imprecisa de certos elementos da interface do programa.
Encontre a seção Display/Window
e defina a largura para 800
e a altura para 600
. Também nesta seção, defina Stretch/Mode
como 2D
e Aspect
como Keep
. Isso evitará esticar e deformar o conteúdo da janela ao alterar seu tamanho, mas para impedir que a janela seja redimensionada, basta desmarcar a caixa Redimensionável. Eu aconselho você a brincar com essas opções.
Agora vá para a seção Rendering/Quality
e ative Use Pixel Snap
no painel direito. Para que é isso? As coordenadas dos vetores no Godot Engine são números de ponto flutuante. Como os objetos não podem ser desenhados apenas meio pixel, essa discrepância pode causar defeitos visuais em jogos que usam pixelart
. E vale a pena notar que em 3D essa opção é inútil. Tenha isso em mente.
Cena do jogador
Vamos começar a criar a primeira cena - Player
.
A vantagem de qualquer cena é que, inicialmente, elas são independentes de outras partes do jogo e isso possibilita testá-las livremente e obter o resultado que foi originalmente estabelecido nelas. Em geral, dividir objetos de jogo em cenas é uma ferramenta útil na criação de jogos complexos - é mais fácil detectar erros, fazer alterações na própria cena, enquanto outras partes do jogo não serão afetadas, elas também podem servir de modelo para outros jogos e definitivamente funcionarão da mesma forma. como eles trabalhavam antes da transferência.
Criar uma cena é uma ação trivialmente simples - na guia Scene
, clique em +
(Adicionar / Criar) e selecione o nó Area2D
e altere imediatamente seu nome para não ficar confuso. Este é o nosso nó pai e, para expandir a funcionalidade, você precisa adicionar nós filhos. No nosso caso, são AnimatedSprite
e CollisionShape2D
, mas não vamos nos apressar, mas vamos começar em ordem. Em seguida, "bloqueie" imediatamente o nó raiz:

Se a forma de colisão do corpo (CollisionShape2D) ou o sprite (AnimatedSprite) forem alteradas, esticadas em relação ao nó pai, isso definitivamente levará a erros imprevistos e mais tarde será difícil corrigi-los. Com esta opção ativada, o "pai" e todos os seus "filhos" sempre se moverão juntos. Parece engraçado, mas usar esse recurso é extremamente útil.
AnimatedSprite
Area2D
nó muito útil se você precisar conhecer um evento de sobreposição com outros objetos ou sobre sua colisão, mas por si só é invisível aos olhos e tornar visível o objeto Player
adicione AnimatedSprite
. O nome do nó nos diz que lidaremos com animações e sprites. Na janela Inspector
, vá para o parâmetro Frames
e crie um novo SpriteFrames
. Trabalhar com o painel SpriteFrames
é criar as animações necessárias e carregar os sprites correspondentes nelas. Não analisaremos detalhadamente todos os estágios da criação de animações, deixando isso para estudo independente, apenas direi que deveríamos ter três animações: walk
(animação ambulante), idle
(estado de repouso) e die
(animação de morte ou falha). Não esqueça que o valor de SPEED (FPS)
deve ser 8
(embora você possa escolher um valor diferente - adequado).

Collisionshape2d
Para o Area2D
detectar colisões, você deve fornecer a forma de um objeto. As formas são determinadas pelo parâmetro Shape2D
e incluem retângulos, círculos, polígonos e outros tipos mais complexos de formas, e os tamanhos já foram editados no próprio editor, mas você sempre pode usar o Inspector
para obter um ajuste mais preciso.
Cenários
Agora, para "reviver" nosso objeto de jogo, você precisa definir um script para ele, de acordo com o qual as ações definidas por nós, prescritas neste cenário, serão executadas. Na guia Scene
, crie um script, deixe as configurações padrão, exclua todos os comentários (linhas começando com o sinal '#') e prossiga para declarar as variáveis:
export (int) var speed var velocity = Vector2() var window_size = Vector2(800, 600)
O uso da palavra-chave export
permite definir o valor da variável de speed
na janela do painel Inspector
. Esse é um método muito útil se quisermos obter valores personalizados que sejam convenientes para editar na janela Inspector
. Defina a Speed
como 350
. O valor da velocity
determinará a direção do movimento, e window_size
é a área que restringe o movimento do jogador.
A ordem adicional de nossas ações é a seguinte: usamos a função get_input()
para verificar se a entrada do teclado está sendo feita. Em seguida, moveremos o objeto, de acordo com as teclas pressionadas, e depois reproduziremos a animação. O jogador se moverá em quatro direções. Por padrão, o Godot Engine possui eventos atribuídos às teclas de seta ( Project -> Project Settings -> Input Map
), para que possamos aplicá-las ao nosso projeto. Para descobrir se uma tecla foi pressionada, você deve usar Input.is_action_pressed()
deslizando o nome do evento que deseja rastrear.
func get_input(): velocity = Vector2() if Input.is_action_pressed("ui_left"): velocity.x -= 1 if Input.is_action_pressed("ui_right"): velocity.x += 1 if Input.is_action_pressed("ui_up"): velocity.y -= 1 if Input.is_action_pressed("ui_down"): velocity.y += 1 if velocity.length() > 0: velocity = velocity.normalized() * speed
À primeira vista, tudo parece bom, mas há uma pequena nuance. A combinação de várias teclas pressionadas (por exemplo, para baixo e para a esquerda) causará a adição de vetores e, neste caso, o jogador se moverá mais rápido do que se ele simplesmente se movesse para baixo. Para evitar isso, usaremos o método normalized()
- ele retornará o comprimento do vetor para 1
.
Portanto, os eventos de pressionamento de tecla foram rastreados, agora você precisa mover o objeto Player
. A função _process()
nos ajudará com isso, que é chamada toda vez que ocorre uma alteração de quadro, por isso é aconselhável usá-la para os objetos que geralmente mudam.
func _process(delta): get_input() position += velocity * delta position.x = clamp(position.x, 0, window_size.x) position.y = clamp(position.y, 0, window_size.y)
Espero que você observe o parâmetro delta
, que por sua vez é multiplicado pela velocidade. É necessário explicar o que é. O mecanismo de jogo é inicialmente configurado para operar a uma velocidade de 60 quadros por segundo. No entanto, pode haver situações em que o computador ou o próprio mecanismo Godot diminui a velocidade. Se a taxa de quadros não for consistente (o tempo necessário para que os quadros sejam alterados), isso afetará a "suavidade" do movimento dos objetos do jogo (como resultado, o movimento é "irregular"). "Godot Engine" resolve esse problema (como a maioria dos mecanismos similares) introduzindo a variável delta
- fornece o valor pelo qual os quadros foram alterados. Graças a esses valores, você pode "alinhar" o movimento. Preste atenção a mais uma função notável - clamp
(retorna o valor dentro de dois parâmetros especificados), graças a isso, podemos limitar a área que o Player
pode mover, simplesmente definindo o valor mínimo e máximo da área.
Não esqueça de animar nosso objeto. Observe que quando o objeto se move para a direita, você precisa inverter AnimatedSprite
(usando flip_h
) e nosso herói olhará na direção em que ele está se movendo diretamente ao se mover. Verifique se no AnimatedSprite
o parâmetro Playing
está ativado para que a animação comece a ser reproduzida.
if velocity.length() > 0: $AnimatedSprite.animation = "walk" $AnimatedSprite.flip_h = velocity.x < 0 else: $AnimatedSprite.animation = "idle"
Nascimento e morte
Ao iniciar o jogo, a cena principal deve ser informada das principais cenas sobre sua prontidão para iniciar um novo jogo; no nosso caso, você deve informar o objeto Player
sobre o início do jogo e definir parâmetros iniciais para ele: posição da aparência, animação padrão, executar set_process
.
func start(pos): set_process(true)
Também fornecemos o evento de morte de um jogador quando o tempo acabar ou o jogador se set_process (false)
com um obstáculo, e definir set_process (false)
fará com que a função _process ()
não seja mais executada para esta cena.
func die(): $AnimatedSprite.animation = "die" set_process(false)
Adicionando colisões
Foi a vez de fazer o jogador detectar colisões com moedas e obstáculos. Isso é mais facilmente implementado usando sinais. Os sinais são uma ótima maneira de enviar uma mensagem para que outros nós possam detectá-los e responder. A maioria dos nós já possui sinais internos, mas é possível definir sinais de "usuário" para seus próprios propósitos. Os sinais são adicionados se você os declarar no início do script:
signal pickup signal die
Navegue pela lista de sinais na janela Inspector
(guia Node
) e preste atenção aos nossos sinais e aos sinais que já existem. Agora estamos interessados em area_entered ()
, pressupondo que os objetos com os quais a colisão ocorrerá também sejam do tipo Area2D
. Conectamos o sinal area_entered ()
usando o botão Connect
e, na janela Connect Signal
, selecione o nó destacado (Player), deixe o restante por padrão.
func _on_Player_area_entered( area ): if area.is_in_group("coins"):
Para que os objetos possam ser facilmente detectados e interagidos, eles precisam ser identificados nos grupos apropriados. A criação dos próprios grupos agora é omitida, mas definitivamente retornaremos a eles mais tarde. A função pickup()
determina o comportamento da moeda (por exemplo, ela pode reproduzir uma animação ou som, excluir um objeto etc.).
Coin Scene
Ao criar uma cena com uma moeda, você precisa fazer tudo o que fizemos com a cena "Player", exceto que haverá apenas uma animação (destaque) no AnimatedSprite
. Speed (FPS)
pode ser aumentada para 14
. Também mudaremos a escala do AnimatedSprite
- 0,5, 0,5
. E as dimensões do CollisionShape2D
devem corresponder à imagem da moeda, o principal é não dimensioná-la, ou seja, alterar o tamanho usando os marcadores apropriados no formulário no editor 2D, que
ajusta o raio do círculo.

Grupos são um tipo de identificação de nós que permite identificar nós semelhantes. Para que o objeto Player
reaja ao toque com moedas, as moedas devem pertencer ao grupo, vamos chamá-lo de coins
. Selecione o nó Area2D
(com o nome "Moeda") e atribua uma tag a ele na guia Node -> Groups
, criando o grupo correspondente.

Para o nó Coin
, crie um script. A função pickup()
será chamada pelo script do objeto Player
e informará à moeda o que fazer quando funcionar. O método queue_free()
excluirá com segurança um nó da árvore com todos os nós filhos e limpará a memória, mas a exclusão não funcionará imediatamente, será movida primeiro para a fila a ser excluída no final do quadro atual. Isso é muito mais seguro do que excluir um nó imediatamente, porque outros "participantes" (nós ou cenas) no jogo ainda podem precisar desse nó para existir.
func pickup (): queue_free ()
Conclusão
Agora podemos criar a cena Main
, arrastar as duas cenas: Player
e Coin
mouse para o editor 2D e verificar como o movimento do jogador e seu contato com a moeda funcionam iniciando a cena (F5). Bem, estou com pressa de dizer que a primeira parte da criação do jogo "Like Coins" está concluída, deixe-me sair e agradecer a todos pela atenção. Se você tem algo a dizer, complemente o material ou viu erros no artigo, informe-o escrevendo um comentário abaixo. Não tenha medo de ser duro e crítico. Seu "feedback" informará se estou indo na direção certa e o que pode ser corrigido para tornar o material ainda mais interessante e útil.