Vagar (Wander)

Técnica de algoritmo que faz o agente vagar pelo ambiente virtual sem um destino definido. Esse comportamento pertence ao steering behaviors.

Categoria de Programação

Postado em 19 maio 2023

Atualizado em 19 maio 2023

Palavras-chave: steering,behaviors,comportamentos,navegacao,navegação,algoritmo,ambiente,virtual,seek,buscar,fugir,flee

Visualizações: 462



Steering behaviors (comportamentos de navegação) são um conjunto de técnicas que simulam o comportamento de animais, como a revoada de pássaros. Foi introduzido pela primeira vez em 1987, por Craig Reynolds na obra “Stanley and Stella in Breaking the Ice” (Stanley e Stella em quebrando o gelo). Desde então, esse algoritmo começou a ser utilizado em vários ocasiões, como filmes, jogos e materiais de ornitologia.

Apesar da simplicidade de implementação, steering behaviors traz resultados ótimos. Isso faz com que muitos desenvolvedores optem por sua adoção. As seguintes postagens de steering behaviors já foram adicionadas:

Como continuação das postagens acima, nessa postagem será discutido o comportamento wander (vagar). Esse comportamento simula um objeto que vaga aletoriamente e sem rumo pelo mapa, podendo ser útil para aplicação de comportamentos de deslocamento de NPCs em jogos de RPG.

O que é o comportamento wander (vagar)?

O comportamento “wander” é um algoritmo de simulação de movimento aleatório. O agente vaga aleatoriamente pelo ambiente virtual, sem nenhum destino.

Craig Reynolds explica em seu site que uma simples implementação que gera uma força de navegação por cada frame pode ser simples, porém esse tipo de implementação realiza movimentos não muito satisfatórios. O agente se torna inquieto, alternando a sua direção rapidamente em múltiplas direções, resultando em uma moção nada natural. Invés disso, uma boa forma de lidar com esse problema é manter a direção de navegação e mudando em pequenas proporções em cada frame. Assim, o agente não mudará repentinamente a sua direção.

Um método bastante eficiente é colocar uma esfera um pouco a frente do agente. O comportamento “vagar” terá uma força que irá ser restringida pelos limites dessa esfera.

wander steering behaviors

O valor de variação de direção não será descartado a cada frame. Esse valor será acumulado e ajustado com um limite pela superfície da esfera. O raio da esfera determina a força máxima do comportamento “vagar” e a distância entre o ponto de variação e o agente determina o grau de variação da direção.

Apesar de ser um comportamento aleatório, “vagar” é um comportamento controlado. Esse método pode ser útil em jogos, evitando movimentos lineares e previsíveis de atores, tornando o jogo mais emocionante.

O ponto vermelho na imagem acima é o resultado do ângulo de variação. O ângulo é definido por um valor aleatório dentro de uma esfera de valor limitado para que não haja variações muito radicais de valor, mantendo a suavidade no movimento do agente.

Implementando os requisitos básicos

Antes de iniciar a implementação do algoritmo de comportamento “vagar”, o ambiente virtual deve estar preestabelecido.

A classe “Vehicle” é o agente que irá vagar pelo plano virtual. O agente irá possuir os seguintes atributos (variáveis locais):

  • Posição
  • Velocidade
  • Ângulo “vagar”

Os atributos irão mudar constantemente durante a execução do algoritmo.

Seguindo adiante, constantes irão ser definidas no escopo global do código e nunca irão mudar durante a execução do algoritmo. São constantes globais:

  • Velocidade máxima
  • Força máxima
  • Raio do agente (Triângulo)
  • Distância até o centro da esfera
  • Raio da esfera

Os valores das variáveis acima podem ter o seu valor influenciado pelo ambiente virtual (contexto do software). Esses valores devem ser ajustados para que o comportamento “wander” possa ser executado com efetividade.

const MAX_FORCE = 0.2 // Força máxima
const MAX_SPEED = 2 // Velocidade máxima
const CIRCLE_DISTANCE = 50 // Distância até esfera
const AGENT_R = 7 // Raio do triângulo
const OUT_CIRCLE_R = 25 // Raio da esfera

Dentro da classe veículo, definimos o construtor e os atributos. Exceto o ângulo, todos os atributos serão vetores.

class Vehicle {
  constructor(x, y) {
    this.pos = createVector(x, y) // Posição
    this.velocity = createVector(2, 0) // Velocidade atual
    this.wanderAngle = 0 // Ângulo vagar
  }
}

Em seguida, definimos a função “draw” que irá exibir o agente na tela:

class Vehicle {
	...
	draw() {
		// Desenha um triângulo com tamanho 10
		let triangle = triangle(this.pos.x, this.pos.y, AGENT_R * 2)

		// Aponta a cabeça do triângulo para frente
		triangle.rotate(this.velocity.heading);
	}
}

Como implementar o comportamento wander

Uma vez que os requisitos básicos foram definidos, implementamos o comportamento “wander”.

class Vehicle {
	...
    wander() {
	    // TODO
    }
}

Para facilitar a implementação e a testagem, exibimos na tela os seguintes elementos:

  • Esfera
  • Centro da esfera
  • Distância do agente até a esfera

Os três elementos acima serão exibidos usando a função wander.

wander() {
    // Copia o vetor da velocidade
    let spherePos = this.velocity.clone()
    // Normaliza, multiplica pela distância até o circulo e soma com a posição atual
    spherePos.normalize().mult(CIRCLE_DISTANCE).add(this.pos)

	// Exibi a esfera
	circle(spherePos.x, spherePos.y, OUT_CIRCLE_R * 2)
	// Exibi o centro da esfera
	circle(spherePos.x, spherePos.y, 5)
	// Exibi a distância até o centro da esfera
	line(this.pos.x, this.pos.y, spherePos.x, spherePos.y)
}

Finalmente instanciamos o agente para vermos o resultado.

var vehicle;

start() {
	// Instancia o agente
	vehicle = new Vehicle(width / 2, height / 2)
}

update() {
	// Exibi o agente
	vehicle.draw()
	// Exibi os elementos para testar o comportamento vago
	vehicle.wander()
}

O resultado será o agente apontando para a esfera.
wander steering behaviors test

A posição da esfera e dos outros elementos de exibição estão funcionando perfeitamente. Uma vez que podemos ver a esfera de ajuste de direcionamento, podemos começar a implementar o código principal.

Dentro da função “wander”, calculamos a variação de direção usando o ângulo do agente. Em seguida, partindo do centro da esfera, calculamos a força de direção e subtraímos esse valor pela posição atual.

wander() {
    // Copia o vetor da velocidade
    let spherePos = this.velocity.clone()
    // Normaliza, multiplica pela distância até o circulo e soma com a posição atual
    spherePos.normalize().mult(CIRCLE_DISTANCE).add(this.pos)

	// Cálculo de variação de direcionamento
	let displacement = new Vector(0, 0)
	// Calcula a força de direção com coordenadas polares
	displacement.x = OUT_CIRCLE_R * cos(this.angle)
	displacement.y = OUT_CIRCLE_R * sin(this.angle)

	// Calcula a direção de deslocamento
	let direction = spherePos + displacement
	// Calcula comportamento de vagar
	let vagar = this.pos - direction
	vagar.limit(MAX_FORCE)
	
	...
	
	return vagar
}

O valor da variável “vagar” é retornado pela função “wander”. Usaremos esse valor dentro da função “move”.

class Vehicle {
    ...
    move () {
	    let vagar = this.wander()
		// Adiciona o valor de wander na velocidade
		this.velocity.add(vagar)
	    this.velocity.limit(MAX_SPEED)
	    // Muda a posição
	    this.pos.add(this.velocity)
	    // No final, adiciona uma pequena variação aleatória ao ângulo
	    this.angle += random(-0.5, 0.5)
    }
}

Finalmente, chamamos a função “move” para o agente começar a se locomover.

update() {
	// Exibi o agente
	vehicle.draw()
	// Move o agente
	vehicle.move()
}

Para complementar, exibimos o ponto de variação e a distância até esse ponto.

wander() {
	...
	// Exibi a variação da direção pelo ângulo
	circle(displacement.x, displacement.y, 7)
	line(this.pos.x, this.pos.y, direction.x, direction.y)
	...
	return vagar
}

O algoritmo deve mostrar o vetor que muda aleatoriamente cada frame. Apesar de haver múltiplas atualizações por segundo, o agente ainda tem uma movimentação suave e satisfatória.

Conclusão

“Wander” é um algoritmo de comportamento que simula um agente vagando pelo ambiente virtual. Esse comportamento pertence ao Steering Behaviors, sendo apenas um dos diversos comportamentos diponíveis. Sua implementação é simples e traz resultados eficientes. Pode ser implementado em jogos, robôs e em softwares educativos.

Projetos práticos

Criando um sistema de mini garagem automatizada integrada com um sistema de monitoramento independente

Desenvolvimento de um sistema de monitoramento que exibi todos os eventos que acontecem na garagem automatizada, como abertura de portões ou ocupação de vagas.

Desenvolvendo o campo de visão de um personagem em um plano 2D

Detectando objetos que entram dentro do campo de visão do personagem. Útil para servir de "gatilho" para eventos em um jogo.

Criando um sistema de integração contínua (CI/CD)

Fazendo a integração contínua de Jenkins, Sonatype Nexus, Sonatype, JUnit e Gradle para automatizar processos repetitivos. Prática bastante usada em tecnologias de DevOps.

Criando artes de texto usando imagens

Convertendo imagens para ascii art usando o valor da intensidade das cores cinzentas.

Integrando Laravel com o protocolo MQTT para comunicação entre dispositivos

Projeto de comunicação entre dois dispositivos ESP8266 e Raspberrypi4. Laravel irá funcionar como servidor e receptor de dados de temperatura e umidade coletados com o DHT11.

Veja também

Os robôs estão aprendendo por conta própria?

Já não é mais novidade saber que os robôs não precisam mais da orientação de um humano para aprender. Além disso, os robôs já superam os humanos em muitas áreas...

A biometria digital é uma grande promessa ao futuro da tecnologia

Muitos serviços já utilizam a autenticação biométrica integrada com a inteligência artificial para melhorar a experiência do usuário, além de melhorar a segurança.

Blockchain Parte2

PoW atua como um intermediário não-humano entre os negociadores de criptomoedas. Em média, uma transação em bitcoin dura 10 minutos.

Perseguir (pursuit) e desviar (evade)

Dois tipos de comportamentos que preveem o trajeto do alvo. Em outras palavras, esses dois algoritmos tomam decisões se baseando em informações do futuro.

Linguagem de programação

A linguagem de programação é um conjunto de instruções que possuem um padrão de escritas, sendo um intermediário entre o programador humano e a máquina.

Variáveis na programação

As variáveis são elementos responsáveis por armazenar informações temporariamente ou perpetuamente durante a execução de um programa ou algoritmo.