Busca de Caminho em Grade
Neste tutorial, faremos uma simulação de busca de caminho baseada em uma grade de array bidimensional. Isso nos dará a ideia básica de como criar atividades de busca de caminho para nossos jogos. Vamos visualizar a grade usando objetos quadrados vazios como ladrilhos e um objeto redondo como nosso avatar que pode se mover nessa área da grade com nosso comando.
I. Configurando os objetos
Usaremos apenas quatro objetos em nosso projeto. Nosso avatar verde, um ladrilho azul, uma barreira branca e o rótulo da grade para configurar e visualizar nossa grade.
Avatar
Nosso avatar é um objeto vazio que tem uma escala x e y de 50%. Configure sua colisão para uma forma redonda para que pareça com o que está na imagem abaixo. Este objeto terá três atributos pré-definidos: no ladrilho, ladrilho anterior e ladrilho alvo. Defina os valores padrões desses atributos como zero para que eles não tenham um valor nulo quando tentarmos recuperá-los mais tarde.
Objeto Ladrilho
Crie outro objeto vazio que será usado para visualizar os ladrilhos em nossa grade. Sua escala também é 50% e possui apenas um atributo pré-definido: no ladrilho. Defina também este valor como zero.
Objeto Barreira
Crie outro objeto vazio que servirá como barreiras em nossa grade. Este é um objeto vazio branco com uma escala de 40%. Nosso avatar não poderá atravessar um ladrilho que tenha uma barreira em cima dele.
Rótulo da Grade
Este é apenas um rótulo que terá os comportamentos que permitirão a configuração e visualização de nossa grade. Ele tem atributos pré-definidos: início x com um valor de 4, e início y com um valor de 3. Esses valores são deslocamentos que serão usados como referência ao gerar nossos ladrilhos para posicionar nossa grade ordenadamente no centro.
Atributos Pré-definidos do Avatar/Ladrilho:
Definimos um ladrilho aqui como um array de 2 tamanhos que terá um valor x e y baseado em nossa grade.
- no ladrilho - este é o valor do ladrilho que nosso objeto está atualmente na nossa grade
- ladrilho anterior - um ladrilho que foi atravessado anteriormente pelo nosso avatar
- ladrilho alvo - o ladrilho que nosso avatar irá para
II. Configurando a grade
Dentro do rótulo da grade é onde definiremos nosso array 2D e a geração de nossa grade. Existem 2 pontos principais neste objeto: configurar o array e visualizar o array. Vamos primeiro fazer a configuração do array.
Configurar o array - pacote
Primeiro, crie um array vazio chamado 'Grade'. Este array conterá nosso array bidimensional. Teremos um contêiner caixa chamado 'contagem de linhas x' que tem um valor de 24 e outro array vazio chamado 'linha y' que tem 18 valores vazios.
O primeiro comportamento em nosso pacote é um loop com um número de repetições de 'contagem de linhas x'. Para cada passo deste loop, adicionaremos uma linha y vazia ao 'array Grade'. Isso criará um array dentro de um array com dimensão de 24x18.
Note que conectamos um comentário inativo no início de nosso pacote para negar a execução automática deste comportamento raiz. Um comportamento raiz é um comportamento que não é acionado com base em nenhum evento e é colocado abertamente na interface.
Visualizar a grade - pacote
A principal coisa que faremos aqui é percorrer cada valor do nosso 'array Grade' e gerar um objeto ladrilho. Também adicionaremos uma condição em nosso loop que permitirá a geração de uma barreira branca em cima do objeto ladrilho.
Primeiro, obtenha a contagem de array de nossa 'array linha y', o valor do atributo 'início x' deste objeto e o 'início y'.
Crie um loop que tenha uma repetição de 'contagem de linhas x' e, para cada passo deste loop, adicionaremos o valor de índice daquele loop e o valor do atributo 'início x'. Isso resulta em uma posição x absoluta que usaremos para posicionar nossos ladrilhos gerados mais tarde. Em seguida, temos o loop 'linha y' que tem uma repetição de 'contagem de linhas y'. Para cada passo desse loop, iremos adicionar o valor de índice daquele loop e o valor do atributo 'início y', resultando agora na posição y absoluta.
Após adicionar os valores do loop 'linha y', geraremos o objeto azul. Defina o número de objetos vivos para 999, pois precisaremos de muitos deles para nossa grade, também com uma duração de 0. Em seguida, mova o objeto gerado para um ponto x com um valor do 'adicionar valores' do loop x e o ponto y com valor do 'adicionar valores' do loop y.
Em seguida, adicione um array com 2 valores vazios chamado 'No ladrilho' que usaremos apenas como um espaço reservado de array. Após mover o objeto ladrilho, modifique o array 'No ladrilho' substituindo seu valor no índice 0 pelo valor do 'loop linha x'. Em seguida, adicione outra modificação de array que substitua o valor no índice 1 pelo valor do índice da linha y. Esta é a coordenada x e y de nossa grade que o objeto terá como atributo 'no ladrilho'.
Agora, defina o atributo do objeto gerado com uma chave dinâmica, 'no ladrilho', e com um valor de 'No ladrilho - array'.
Ainda sob o loop da linha y, está a condição de gerar o objeto barreira branca. Teremos uma chance de 2 em 5 de executar este pacote, o que adicionará aleatoriedade à nossa grade. Em seguida, marcaremos um valor de 1 nas coordenadas x e y daquela em nosso 'Grade' array que nos diz que aquela coordenada tem uma barreira gerada.
Primeiro, gere um número aleatório de 1 a 5. Se esse número for menor ou igual a 2, geraremos a barreira. Defina seu número de objetos vivos para 999 e mova esse objeto para o mesmo ponto que o ladrilho azul que geramos antes, também com uma duração de 0.
Em seguida, armazene a informação de que essa coordenada foi ocupada por uma barreira, se foi gerada. Fazemos isso marcando aquela coordenada com um valor de 1. Primeiro, obtenha o valor no índice 'loop linha x' do array 'Grade'. Este valor nos dará um array de uma 'linha y'. Vamos modificar essa 'linha y' substituindo seu valor no índice 'loop linha y' pelo valor 1, que é o valor marcado. Como essa modificação de valor se aplica apenas àquele valor, e não à 'Grade' em si, ainda temos que modificar o array 'Grade'. Substitua o valor no índice 'loop linha x' do array 'Grade' pelo valor de 'modificar linha y - array'.
Uma vez jogado, deve resultar nesse tipo de forma.
III. Ao pressionar o Ladrilho
Para poder interagir com a grade, precisaremos de um comportamento de pacote sempre que pressionarmos um ladrilho azul. O primeiro pressionar resultará na aparência do nosso avatar em nossa grade, e qualquer pressionar sucessivo após esse evento iniciará sua busca de caminho.
Dentro do objeto azul está um pacote de comportamento que possui 3 pontos principais: redefinir o ladrilho anterior do nosso avatar, definir seu ladrilho atual/definir seu ladrilho alvo, em seguida, definir uma animação de cor para visualizar o evento de toque na tela.
Primeiro, obtenha o atributo 'no ladrilho' do objeto ladrilho. Defina o atributo 'ladrilho anterior' do nosso avatar como 0. Nosso avatar será configurado para evitar voltar a um 'ladrilho anterior', por isso redefinimos o 'ladrilho anterior' em toda pressão do ladrilho.
Em seguida, obtenha o atributo 'no ladrilho' do nosso avatar. A primeira condição se é se o valor 'no ladrilho' é igual a zero. Isso significa que se o avatar ainda não apareceu, isso resultará em verdadeiro. Se for verdadeiro, definimos seu atributo 'no ladrilho' com o valor do atributo 'no ladrilho' do objeto ladrilho. Então movemos a posição do nosso avatar obtendo a posição do objeto ladrilho, apontando seus valores x e y para esse ponto com uma duração de 0.
Se o valor 'no ladrilho' não for igual a zero, definiremos o atributo 'ladrilho alvo' do nosso avatar com o valor do atributo 'no ladrilho' do objeto ladrilho. Isso significa que nosso avatar já está em nossa grade, e então podemos executar o pacote de comportamento 'encontrar caminho'. Ainda não temos esse comportamento, mas resolveremos isso novamente após fazermos a parte posterior deste tutorial para o pacote 'encontrar caminho'.
Agora que configuramos corretamente nosso avatar em nossa grade, teremos que visualizar este evento de pressão. Primeiro, teremos um comportamento raiz 'obter cor' para obter sua cor original. Então, após o evento de pressão, definiremos a cor do objeto ladrilho para preto com uma duração de 0, e então configuraremos sua cor de volta ao seu valor original com uma duração de 0.2.
pressionar um ladrilho azul deve resultar nisso.
IV. Executar Pacote Encontrar Caminho
Para esta última parte de nosso tutorial, faremos o algoritmo que nos permite encontrar o ladrilho mais próximo que nosso avatar pode ocupar para alcançar seu destino. Este pacote será executado repetidamente para cada passo do ladrilho que nosso avatar se move em nossa grade.
Configuraremos o algoritmo dentro de nosso objeto avatar que terá três pontos principais: encontrar os ladrilhos adjacentes, encontrar o ladrilho adjacente mais próximo e o movimento para aquele ladrilho adjacente.
Encontrando os ladrilhos adjacentes
Nesta parte, coletaremos todos os ladrilhos adjacentes que nosso avatar poderá atravessar. Vamos verificar seus quatro ladrilhos adjacentes de direção e ver se esses ladrilhos possuem uma barreira em cima deles ou se foram pisados anteriormente.
Primeiro adicione nosso array 'Ladrilhos adjacentes'. Um array 'Direção' com 2 valores vazios, e os quatro arrays direcionais que têm 2 valores cada: N (0,1), S (0,-1), E (1,0), W( -1,0).
O primeiro comportamento em nosso pacote é limpar nossos ladrilhos adjacentes. Como faremos este pacote repetidamente, precisamos que nossos 'ladrilhos adjacentes' coletados sejam redefinidos a cada vez. Os próximos quatro comportamentos são modificações para o array 'Direção'. Definimos o array do array 'Direção' quatro vezes com os quatro arrays direcionais e, em seguida, executamos o pacote abaixo. Fazemos isso para criar um loop com diferentes valores de array 'Direção' a cada vez.
Agora que temos a direção, temos que combinar seus valores x e y com o atributo 'no ladrilho' de nosso avatar. Então poderemos obter nosso valor alvo no array 'Grade' para saber se aquele ladrilho estava marcado com uma barreira.
'Direção x' é o valor do array 'Direção' no índice 0, 'obter no ladrilho' x é o valor de 'obter no ladrilho' no índice 0. O alvo x é os valores aditivos de 'direção x' e 'obter no ladrilho x'. O mesmo vale para os valores y, mas com um índice alvo de 1.
'Linha y alvo' é o valor do array 'Grade' no índice 'Alvo x'. E então o 'índice alvo na linha y' será o valor do array 'Linha y alvo' no índice de 'Linha y alvo'. Isso é a coordenada em nossa grade que poderá nos informar se está marcada com uma barreira.
Se o valor no 'índice alvo na linha y' for 1, então aquele ladrilho alvo foi marcado como bloqueado. Mas se o valor não for igual a 1, então podemos continuar em nosso pacote.
Como nosso Alvo x e y passou nossa condição, adicionamos um novo array de ladrilho vazio chamado 'Novo ladrilho adjacente'. Isso armazenará os valores de Alvo x e y como um array de ladrilhos. Definiremos o valor de Alvo x para o índice 0 de 'Novo ladrilho adjacente' e Alvo y para seu índice 1.
Agora obtenha o atributo 'ladrilho anterior' de nosso avatar. Se o 'ladrilho anterior' não for igual ao 'novo ladrilho adjacente', isso significaria que o novo ladrilho não foi atravessado anteriormente. Então, podemos adicionar com segurança o 'Novo ladrilho adjacente' ao array 'Ladrilhos adjacentes' anexando-o. Definiremos o valor de 'ladrilho anterior' mais tarde, após mover nosso avatar para outro ladrilho.
"Você pode expandir este pacote fazendo um array de 8 direções que permite que seu avatar se mova em direções diagonais."
Encontrando o ladrilho adjacente mais próximo
Agora que coletamos nossos ladrilhos adjacentes confiáveis, precisamos apenas obter o ladrilho adjacente que está mais próximo do ladrilho alvo do nosso avatar. Faremos o cálculo usando uma fórmula de distância fornecida pelos valores x e y do nosso ladrilho alvo e os ladrilhos adjacentes.
Existem dois pontos principais neste pacote: a inicialização de variáveis para cálculo e o cálculo das distâncias dos ladrilhos dentro de um loop.
a. Inicialização de variáveis
Primeiro, obtenha a contagem do array de nossos ladrilhos adjacentes. Então, obtemos o atributo 'ladrilho alvo' de nosso avatar e obtemos seus valores x e y. Adicionaremos 2 novas caixas: a 'Distância mínima' e o 'Índice do ladrilho alvo'. Definimos o valor inicial de 'Distância mínima' como 9999 e o valor de 'Índice do ladrilho alvo' como 0. A distância mínima é definida para um número alto porque precisamos da menor distância a partir do início. O índice do ladrilho alvo é nosso índice de referência no array 'Ladrilhos adjacentes' que tem a menor distância até nosso 'ladrilho alvo'.
Nosso objetivo principal aqui é obter o índice do ladrilho dentro de nosso array 'Ladrilhos adjacentes' que está mais próximo do nosso 'ladrilho alvo'.
b. Cálculo das distâncias dos ladrilhos
Neste pacote, faremos o cálculo dentro de um loop que faremos para cada ladrilho adjacente. O loop se repete pela 'contagem de ladrilhos adjacentes' e obteremos o valor do ladrilho do array 'Ladrilhos adjacentes' usando o índice daquele loop.
Obtenha os valores x e y daquele ladrilho adjacente e então calcularemos a distância entre nosso 'ladrilho alvo' e o 'ladrilho adjacente' usando esta fórmula:
distância = sqrt((x2 - x1)^2+(y2 - y1)^2)
x1 = Alvo x
x2 = Adjacente x
y1 = Alvo y
y2 = Adjacente y
Primeiro subtraímos seus valores x e y, multiplicamos a si mesmos para obter seus valores exponenciais, adicionamos esses valores e, em seguida, tiramos a raiz quadrada dos valores adicionados, para obter o valor da distância.
Se o valor da 'Distância' for menor que o valor do contêiner de 'Distância mínima', então definiremos o valor do 'índice do ladrilho alvo' para o índice atual do loop, que é o índice de nosso ladrilho recuperado dentro do array 'Ladrilhos adjacentes'. Também definimos o valor do contêiner de 'Distância mínima' com o valor de 'Distância' para que possamos compará-lo com o próximo ladrilho do nosso loop.
Após o término do loop, comparamos cada um de nossos ladrilhos adjacentes e obtivemos o valor do índice do ladrilho adjacente que está mais próximo do nosso 'ladrilho alvo'.
Movimento para o ladrilho adjacente
Neste último pacote do nosso tutorial, moveremos nosso avatar para o ladrilho adjacente mais próximo e refaremos todo o pacote 'Encontrar Caminho' se ainda não nos movemos para nosso 'ladrilho alvo'.
A primeira coisa a fazer é verificar se nossa 'contagem de ladrilhos adjacentes' é maior que 0. Isso é para garantir que nos moveremos apenas se recuperarmos pelo menos um ladrilho adjacente confiável.
Então, 'Obtenha o ladrilho mais próximo' usando nosso valor 'índice do ladrilho alvo' do pacote anterior para obter o valor do array do array 'Ladrilhos adjacentes'.
Para obter o exato ponto onde nosso avatar se moverá, precisaremos dos valores de ladrilho x e y desse ladrilho, e também obter os valores dos atributos 'início x' e 'início y' de nosso rótulo da 'Grade'. Assim, somamos o valor x do nosso 'ladrilho mais próximo' e o valor de 'início x', e também o mesmo com os valores y. Esses valores adicionados são nossos pontos x e y alvo onde nosso avatar se moverá.
Antes de nos movermos para esse ponto, definimos o 'ladrilho anterior' do nosso avatar com seu valor atual de atributo 'no ladrilho'. Podemos obter esse valor 'no ladrilho' dos pacotes anteriores. Movemos nosso avatar para nossos pontos alvo, com uma duração de 0.2.
Após a finalização do comportamento 'Mover para o ponto', agora definimos o valor do atributo 'no ladrilho' do nosso avatar com o valor do array 'Obter ladrilho mais próximo'. Se o valor do array 'Obter ladrilho mais próximo' não for igual ao nosso 'ladrilho alvo', então executaremos o pacote 'Encontrar Caminho', assim refazendo todo o pacote novamente. O valor do atributo 'ladrilho alvo' pode ser obtido do pacote anterior.
Ao pressionar qualquer ladrilho azul, e após a aparência do nosso avatar na grade, o pacote 'Encontrar Caminho' será executado. Isso acionará o movimento do avatar de ladrilho para ladrilho.
Conclusão
Neste tutorial, aprendemos a fazer uma atividade de busca de caminhos de objetos usando um array que chamamos de 'Grade', que é usado para armazenar informações se aquele ladrilho estava ocupado ou não. Você pode expandir essa ideia, usando ids de objetos como armazenamento de informação em vez de apenas um número digitado para nosso array 'Grade'. Isso nos dará informações mais confiáveis que podemos usar ao fazer busca de caminhos. Por exemplo, podemos obter os atributos daquele id de objeto para saber se está vivo ou não, se permitirá que possamos pisar em seu ladrilho ou não.
Este tutorial apenas serviu a ideia básica por trás da busca de caminho. Uma desvantagem disso é que não cria o caminho mais curto possível para um ladrilho alvo e apenas verifica seu ladrilho adjacente atual. Isso pode resultar em um loop de movimento que não leva a lugar algum.
No entanto, isso pode ser resolvido expandindo nosso algoritmo de busca de caminhos. Podemos fazer isso reiterando sobre nosso ladrilho adjacente recuperado para obter seus ladrilhos adjacentes também até encontrarmos nosso ladrilho alvo. Cada ladrilho adjacente encontrado será adicionado a uma lista. Para evitar um loop infinito, adicione uma condição de que, se aquele ladrilho adjacente já foi verificado, aquele ladrilho não será adicionado à nossa lista. Além disso, adicione um limite máximo na contagem de iterações para evitar um loop infinito que é causado pelo ladrilho alvo se for muito longe ou não puder ser encontrado. Uma vez que essa iteração encontre o ladrilho alvo, sairemos dessa iteração e começaremos a mover o avatar de ladrilho para ladrilho usando a lista de ladrilhos.

