-
Neste vídeo vamos criar o
-
script de gerenciamento da fase, que irá
-
gerar proceduralmente nossas fases
-
para que ela seja diferente cada vez que o jogador joga.
-
Vamos começar criando dois scripts vazios,
-
o board manager e o game manager.
-
Clique em Create - C# Script.
-
Chame o primeiro BoardManager.
-
Chame o segundo GameManager.
-
Vamos também criar um game object vazio
-
chamado GameManager.
-
Vamos começar adicionanado nosso código de geração de fase
-
ao script BoardManager.
-
Vamos abrir o MonoDevelop.
-
O script BoardManager irá
-
criar fases
-
geradas aleatoriamente cada vez que
-
o jogador inicia uma nova fase
-
baseado no número da fase atual.
-
A primeira coisa que iremos fazer é adicionar
-
uma declaração de namespace usando System.
-
Faremos isso para podermos utilizar a
-
propriedade serialisable.
-
A propriedade serialisable nos permite
-
modificar como as variáveis serão exibidas
-
no inspector e no editor
-
e para que possamos escondê-las e exibí-las.
-
Iremos também adicionar
-
using Systems.Collections.Generic
-
para que possamos criar listas.
-
Finalmente vamos incluir
-
using Random e vamos
-
configurar-la para ser igual a UnityEngine.Random.
-
Temos que especificar qual Random usar porque há uma classe
-
chamada Random tanto no namespace System
-
como no namespace UnityEngine.
-
Na nossa classe vamos começar
-
declarando uma classe pública serialisable chamada Count.
-
Em Count vamos declarar duas variáveis publicas
-
chamadas minimum e maximum, ambas do tipo int.
-
Vamos também incluir uma instrução
-
de assignment para Count, assim podemos
-
configurar os valores de minimum e maximum
-
quando declaramos uma nova instância de Count.
-
Vamos acrescentar parâmetros Min e Max,
-
que serão utilizados para configurar os valores de
-
minimum e maximum.
-
Em seguida vamos declarar nossas variáveis.
-
Vamos iniciar com as variáveis públicas,
-
as duas primeiras serão um inteiro para colunas,
-
e um inteiro para linhas
-
Essas variáveis irão limitar as dimensões da nossa fase
-
e nos permitirão fazer uma fase
-
maior ou menor simplesmente
-
mudando as variáveis.
-
Por enquanto vamos inicializar ambas com o valor oito
-
isso significa que nossa fase terá um tamanho de oito por oito.
-
Em seguida vamos usar Count para especificar
-
um intervalo randômico de quantas paredes
-
nós queremos criar em cada fase.
-
nessa caso isso significa que teremos
-
um mínimo de cinco paredes por fase,
-
e um máximo de nove paredes por fase.
-
Vamos fazer o mesmo para nossos items de comida.
-
Em seguida vamos declarar algumas variáveis
-
para armazenar os prefabs que iremos gerar
-
na nossa fase.
-
Vamos ter um único game object chamado
-
Exit, pois nossa fase terá somente uma saída.
-
Para os outros objetos vamos utilizar
-
vetores, dessa maneira podemos buscar
-
múltiplos objetos e escolher
-
qual deles queremos gerar
-
entre todas as variações.
-
vamos começar com os tiles do piso.
-
Faremos o mesmo para wallTiles,
-
foodTiles, enemyTiles e nosso outerWallTiles.
-
Vamos preencher cada um desses vetores
-
com nossos prefabs diferentes para serem escolhidos
-
no inspector.
-
Em seguida vamos declarar duas variáveis privadas
-
incluindo um transform chamado boardHolder.
-
Vamos usar BoardHolder apenas para manter a
-
hierarquia limpa, pois vamos
-
criar vários game objects e vamos torná-los todos filhos
-
do BoardHolder
-
para que nós possamos escondê-los na hierarquia
-
evitando que nossa hierarquia fique cheia de objetos.
-
Vamos também declarar uma lista privada
-
de vector3s chamada "gridPos".
-
Vamos utilizá-la para controlar
-
todas as possíveis posições
-
da nossa fase e para controlar se um
-
já foi criado naquela
-
posição ou não.
-
Em seguida vamos declarar uma função chamada
-
InitialiseList que irá retornar void.
-
Em InitialiseList vamos começar
-
limpando nossa lista de grid positions
-
chamando a função Clear na nossa lista.
-
Em seguida vamos usar um par de loops aninhados
-
para preencher a lista
-
com cada posição da nossa fase
-
como são vector3, vamos começar com o eixo X.
-
O primeiro loop irá executar
-
enquanto o eixo X for menor que o número de colunas.
-
E em seguida vamos fazer o mesmo para o eixo Y dentro do primeiro loop.
-
Dentro do loop vamos adicionar
-
um novo vector3 com os valores dos eixos X e Y
-
na nossa lista de grid positions.
-
O que estamos fazendo aqui é criar
-
a lista de possíveis posições
-
onde podemos criar paredes, inimigos e pickups.
-
Estamos faze o loop entre um
-
e columns - 1
-
é para deixar uma borda de tiles
-
diretamente dentro das paredes externas,
-
assim garantimos que não iremos criar
-
uma fase impossível de completar.
-
Em seguida vamos declarar uma nova
-
função privada que retorna void
-
chamada BoardSetup.
-
Vamos usar BoardSetup para
-
configurar a parede externa e
-
o piso da nossa fase.
-
Vamos começar configurando boardHolder para
-
ser igual ao transform de um novo
-
game object chamado Board.
-
Em seguida vamos usar o mesmo padrão
-
de loop para configurar o piso
-
e as paredes externas.
-
Então nós vamos utilizar outro loop for nos
-
eixos X e Y.
-
A razão pela qual cada um desses loops
-
vai de -1 a columns -1 ou rows - 1
-
é porque estamos criando uma borda
-
em volta da parte "ativa" da nossa fase
-
usando os objetos da parede externa.
-
Em seguida vamos escolher os tiles do piso aleatoriamente
-
a partir do nosso vetor de tiles
-
e prepará-los para serem instanciados.
-
O que estamos fazendo aqui é declarar uma
-
variável do tipo GameObject
-
chamada toInstantiate
-
e configurando-a para ser igual
-
a um índice da nosso vetor de game objects chamado floorTiles
-
que estamos escolhendo aleatoriamente
-
entre 0 e o length do vetor de tiles do piso.
-
Isso significa que não temos que pré-configurar o length,
-
podemos simplesmente chamar length e escolher
-
um número dentro do vetor.
-
Em seguida vamos verificar
-
se estamos numa posição que faz parte da parede externa,
-
e nesse caso vamos escolher um
-
tile da parede externa para instanciar.
-
Para isso vamos checar se X é igual a
-
-1 ou ao valor de columns,
-
ou se Y é igual a -1 ou o valor de rows
-
nesse caso vamos instanciar
-
um tile escolhido aleatoriamente do
-
vetor de tiles da parede externa.
-
Uma vez escolhido qual tile queremos
-
instanciar nós vamos efetivamente instanciar o tile.
-
Para isso vamos declarar uma variável do tipo
-
GameObject chamada instance e em seguida vamos configurá-la para
-
o objeto que estamos instanciando.
-
Para isso chamamos Instantiate,
-
passamos como parâmetro o prefab escolhido,
-
num novo vector3
-
baseado na nossa coordenada
-
X e Y atual no loop
-
e vamos utilizar o valor zero para o eixo Z
-
pois estamos trabalhando em 2D.
-
Quaternion.identity significa que o objeto vai ser
-
instanciado sem rotação
-
e vamos fazer o cast para game object.
-
Em seguida configuramos o parent
-
do nosso recém criado game object
-
para boardHolder.
-
BoardSetup vai criar nossos
-
tiles de parede externa e de piso.
-
O que faremos em seguida é
-
começar a escrever algumas funções que irão
-
colocar objetos aleatórios na fase
-
como paredes, inimigos e power ups.
-
Vamos declarar uma nova função
-
que retorna um vector3 chamada RandomPosition.
-
Em RandomPosition vamos declarar
-
um inteiro chamado randomIndex
-
e gerar um número aleatório dentro de um intervalo.
-
O intervalo no qual vamos gerar o número
-
é entre zero
-
e o número de posições
-
armazenadas na nossa lista gridPositions,
-
que iremos acessar usando gridPositions.Count.
-
Em seguida vamos declarar um vector3
-
chamado randomPositions e iremos
-
set it to equal the gridPositions
configurar-lo para ser igual a gridPositions
-
armazenado na lossa lista gridPositions
-
no índice que sorteamos aleatoriamente.
-
Para garantir que não iremos gerar dois objetos
-
no mesmo lugar vamos remover
-
a posição da nossa lista.
-
Fazemos isso usando o comando RemoveAt
-
e passando o índice randomIndex.
-
Em seguida retornamos o valor de
-
randomPosition para utilizar-lo
-
para gerar o objeto numa posição aleatória.
-
Agora que obtivemos uma posição aleatória
-
da nossa lista e nos certificamos que ela não é duplicada,
-
vamos escrever uma função que irá efetivamente
-
gerar os tiles na posição aleatória escolhida.
-
Essa função irá chamar LayoutObjectAtRandom
-
e irá receber três parâmetros.
-
Um vetor de game objects chamado tileArray,
-
um inteiro minimum e um inteiro maximum.
-
A primeira coisa que vamos fazer é
-
declarar um inteiro chamado objectCount
-
e inicializar-lo com um valor aleatório entre
-
minimum e maximum + 1.
-
objectCount vai controlar
-
quantas unidades de um dado objeto
-
vamos criar, por exemplo o número de paredes em uma fase.
-
Em seguida vamos escrever um loop for.
-
Vamos repetir este loop for enquanto
-
i for menos que nosso objectCount,
-
isso quer dizer que vamos gerar o número de objetos
-
especificado por objectCount.
-
Vamos começar escolhendo uma posição aleatória
230
00:11:25,763 --> 00:11:28,480\
chamando a função RandomPosition.
-
Em seguida vamos escolher um tile aleatório
-
do nosso vetor de game objects tileArray para gerar o objeto.
-
Faremos isso gerando um
-
número aleatório usando Random.Range entre zero e tileArray.length.
-
Vamos instanciar o tile que
-
selecionamos na nossa posição aleatória.
-
Podemos apagar as funções start e update.
-
E declarar uma nova função pública que retorna void
-
chamada SetupScene, que recebe um parâmetro do tipo int
-
chamado Level.
-
E repare que SetupScene é a única função pública
-
dessa clase.
-
Essa é a função que será chamada pelo
-
game manager quando for o momento de configurar a fase.
-
Dentro de SetupScene a primeira coisa que vamos fazer
-
é chamar BoardSetup.
-
Em seguida vamos chamar initialiseLise.
-
Vamos chamar LayoutObjectAtRandom
-
e vamos adicionar nosso vetor de wallTiles
-
e também os valores minimo e máximo de wallCount.
-
Em seguida vamos fazer o mesmo para foodTiles.
-
Ao invés de gerar um número aleatório de inimigos
-
vamos gerar um número de inimigos
-
baseado no número da fase
-
usando MathF.Log
-
para gerar uma progressão de dificuldade logaritmica.
-
MathF.Log retorna um número de ponto flutuante (float)
-
então temos que converte-lo para inteiro.
-
Isso quer dizer que teremos um inimigo na fase dois,
-
dois inimigos na fase quatro,
-
três inimigos na fase oito,
-
e a dificuldade vai crescendo
-
conforme o jogador avança de fase.
-
Agora que temos o número de inimigos que queremos gerar
-
vamos posicioná-los usando LayoutObjectAtRandom.
-
Repare que os valores mínimo e máximo nesse
-
caso são os mesmos porque não estamos especificando um intervalo aleatório.
-
Finalmente vamos instanciar a saída.
-
A saída será colocada sempre no mesmo
-
lugar e sempre será o mesmo objeto
-
então vamos apenas chamar
-
Instantiate e passar o prefab Exit.
-
A saída sempre estará no canto superior direito
-
da fase, e é por isso que estamos usando
-
coluna -1 e fila -1
-
e isso significa que se decidirmos mudar o tamanho
-
da fase a saída ainda estará no lugar certo.
-
Vamos salvar o script.
-
Agora que o código de geração de fase está
-
escrito no nosso Board Manager
-
no próximo vídeo iremos começar a escrever
-
o Game Manager e configurar o Game Manager prefab.