Gerando monstros

Nesta parte, vamos fazer os monstros surgirem aleatoriamente ao longo de um caminho. No final, você terá monstros vagando pelo tabuleiro de jogo.

imagem0

Clique duas vezes em Principal.tscn no painel Sistema de Arquivos para abrir a cena Principal .

Antes de traçar o caminho, vamos mudar a resolução do jogo. Nosso jogo tem um tamanho de janela padrão de 1024x600. Vamos configurá-lo para 720x540, uma boa telinha.

Vá para Project -> Project Settings.

imagem1

No menu à esquerda, navegue até Exibir -> janela. À direita, defina a Largura como ''720'' e a Altura como ''540''.

imagem2

Criando o caminho de surgimento

Como você fez no tutorial do jogo 2D, você vai desenhar um caminho e usar um nó PathFollow para gerar locais aleatórios nele.

No entanto, em 3D, é um pouco mais complicado desenhar o caminho. Queremos que ele esteja em torno da vista do jogo para que os monstros apareçam fora da tela. Mas se desenharmos um caminho, não o veremos pela pré-visualização da câmera.

Para encontrar os limites da vista, podemos usar algumas malhas de suporte. Sua janela de exibição ainda deve ser dividido em duas partes, com a visualização da câmera na parte inferior. Se este não for o caso, pressione Ctrl + 2 (Cmd + 2 em macOS) para dividir a sua visão em duas partes. Selecione o nó Câmera e clique na caixa de seleção Preview na parte inferior da janela de exibição.

imagem3

Adicionando cilindros de substituto

Vamos adicionar as malhas substitutas. Adicione um novo nó Espacial como filho do nó Principal e o nomeie Cilindros. Vamos usá-lo para agrupar os cilindros. Como filho dele, adicione um nó MeshInstance.

imagem4

No Inspetor, atribua um CylinderMesh à propriedade Malha.

imagem5

Defina a janela de exibição superior com a visualização ortogonal superior usando o menu no canto superior esquerdo da janela de exibição. Como alternativa, você pode pressionar a tecla 7 do teclado.

|imagem 6|

A grade me causa um pouco de distração. Você pode ligá-la ou desligá-la acessando o menu Exibir na barra de ferramentas e clicando em Exibir grade.

image7

Agora você quer mover o cilindro ao longo do plano do solo, observando a visualização da câmera no inferior da janela de visualização. Eu recomendo usar o encaixe de grade para fazer isso. Você pode alterná-lo clicando no ícone do ímã na barra de ferramentas ou pressionando Y.

image8

Coloque o cilindro de modo que ele fique bem fora da visão da câmera no canto superior esquerdo.

image9

Vamos criar cópias da malha e colocá-las ao redor da área do jogo. Pressione Ctrl + D (Cmd + D no macOS) para duplicar o nó. Você também pode clicar com o botão direito do mouse no nó no painel*Cena* e selecionar Duplicar. Mova a cópia para baixo ao longo do eixo Z azul até que esteja fora da visualização da câmera.

Selecione ambos os cilindros pressionando a tecla Shift e clique no não selecionado e duplique-os.

image10

Mova-os para a direita arrastando o eixo X vermelho.

imagem11

Eles estão um pouco difíceis de ver em branco, não estão? Vamos fazer com que eles se destaquem dando a eles um novo material.

Em 3D, os materiais definem as propriedades visuais de uma superfície, como sua cor, como ela reflete a luz e muito mais. Podemos usá-los para mudar a cor de uma malha.

Podemos atualizar todos os quatro cilindros de uma vez. Selecione todas as instâncias de malha no painel Cena. Para fazer isso, você pode clicar no primeiro e com o Shift apertado clicar no último.

imagem12

No Inspetor, expanda a seção Material e atribua um SpatialMaterial no slot 0.

imagem13

Clique no ícone da esfera para abrir o recurso material. Você obtém uma visualização do material e uma longa lista de seções preenchidas com propriedades. Você pode usá-los para criar todos os tipos de superfícies, de metal a rocha ou água.

Expanda a seção Albedo e defina a cor para algo que contraste com o fundo, como um laranja brilhante.

imagem14

Agora podemos usar os cilindros como guias. Dobre-os no painel Cena clicando na seta cinza ao lado deles. Continuando, você também pode alternar sua visibilidade clicando no ícone de olho ao lado de Cilindros.

image15

Adicione um nó Path como filho de Principal. Na barra de ferramentas, quatro ícones são exibidos. Clique na ferramenta Adicionar ponto, no ícone com o sinal verde "+".

image16

Nota

Você pode passar o mouse sobre qualquer ícone para ver uma dica de ferramenta descrevendo a ferramenta.

Clique no centro de cada cilindro para criar um ponto. Em seguida, clique no ícone Fechar curva na barra de ferramentas para fechar o caminho. Se algum ponto estiver um pouco fora, você pode clicar e arrastar sobre ele para reposicioná-lo.

image17

Seu caminho deve se parecer com isso.

image18

Para gerar posições aleatórias nele, precisamos de um nó PathFollow. Adicione um PathFollow como filho de Path. Renomeie os dois nós para SpawnPath e SpawnLocation, respectivamente. Assim fica mais descritivo para o que vamos usá-los.

image19

Com isso, estamos prontos para programar o mecanismo de geração.

Gerando monstros aleatóriamente

Clique com o botão direito do mouse no nó Principal e adicione um novo script a ele.

Primeiro exportamos uma variável para o Inspetor para que possamos atribuir Mob.tscn ou qualquer outro monstro a ela.

Então, como vamos gerar os monstros processualmente, queremos randomizar os números toda vez que jogamos o jogo. Se não fizermos isso, os monstros sempre surgem seguindo a mesma sequência.

extends Node

export (PackedScene) var mob_scene


func _ready():
    randomize()

Queremos desovar multidões em intervalos regulares de tempo. Para isso, precisamos voltar a cena e acrescentar um temporizador. Antes disso, porém, precisamos atribuir o arquivo Mob.tscn à propriedade mob_scene.

Volte para a tela 3D e selecione o nó principal. Arraste Mob.tscn do painel Sistema de Arquivos para o slot Cena Inimigo no inspetor.

image20

Adicione um novo nó Timer como filho de Principal. Nomeie-o InimigoTimer.

image21

No Inspetor, defina seu Tempo de Espera para ''0,5'' segundos e ative o Autoiniciar para que ele seja iniciado automaticamente quando executarmos o jogo.

image22

Os temporizadores emitem um sinal timeout cada vez que chegam ao final de seu Tempo de espera. Por padrão, eles reiniciam automaticamente, emitindo o sinal em um ciclo. Podemos nos conectar a este sinal a partir do nó Principal para gerar os monstros a cada 0.5 segundos.

Com o MobTimer ainda selecionado, dirija-se ao painel à direita e clique duas vezes no sinal timeout.

image23

Conecte-o ao nó Principal.

image24

Isso o levará de volta ao script, com uma nova função _on_MobTimer_timeout() vazia.

Vamos programar lógica de surgimento do mob. Nós vamos:

  1. Instanciar a cena da mob.

  2. Gera uma posição aleatória no caminho de surgimento.

  3. Obtenha a posição do jogador.

  4. Chame o método initialize() do mob, passando a ele a posição aleatória e a posição do jogador.

  5. Adicione o mob como um filho do nó Principal.

func _on_MobTimer_timeout():
    # Create a new instance of the Mob scene.
    var mob = mob_scene.instance()

    # Choose a random location on the SpawnPath.
    # We store the reference to the SpawnLocation node.
    var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
    # And give it a random offset.
    mob_spawn_location.unit_offset = randf()

    var player_position = $Player.transform.origin
    mob.initialize(mob_spawn_location.translation, player_position)

    add_child(mob)

Acima, ''randf()'' produz um valor aleatório entre ''0'' e ''1'', que é o que o nó PathFollow ''unit_offset'' espera.

Aqui está o script Main.gd completo até agora, para referência.

extends Node

export (PackedScene) var mob_scene


func _ready():
    randomize()


func _on_MobTimer_timeout():
    var mob = mob_scene.instance()

    var mob_spawn_location = get_node("SpawnPath/SpawnLocation")
    mob_spawn_location.unit_offset = randf()
    var player_position = $Player.transform.origin
    mob.initialize(mob_spawn_location.translation, player_position)

    add_child(mob)

Você pode testar a cena pressionando F6. Você deve ver os monstros surgirem e se moverem em linha reta.

image25

Por enquanto, eles se chocam e deslizam um contra o outro quando seus caminhos se cruzam. Trataremos disso na próxima parte.