< Return to Video

2D Roguelike 4 of 14 : Board Manager

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

more » « less
Video Language:
Arabic
Duration:
14:09

Portuguese, Brazilian subtitles

Revisions