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: 535



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

Usando dados fornecidos pelo TSE para simular o gráfico das eleições presidenciais de 2022

Simulação dos gráficos do segundo turno das eleições presidenciais, utilizando python e ferramentas de análise de dados, pandas e jupyter.

Criando um jogo de guerra nas estrelas em javascript usando a biblioteca p5.js

Jogo simples de guerra espacial desenvolvido em javascript. Esse jogo usa cálculos de física para simular efeitos de atrito e inércia.

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.

Desenvolvendo um jogo de quebra blocos em javascript

Programando um jogo clássico de arcade usando javascript e p5.js. O usuário deve quebrar os blocos utilizando uma bola ao mesmo tempo que evita que a bola saia pela parte inferior da tela

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

Ainda nos primórdios da internet discada, o maior medo de um usuário era o telefone tocar...

Esperávamos horas para baixar apenas alguns megabytes. Nessas horas, quando o telefone tocava nós fazíamos de tudo para não atender o telefone. Mas infelizmente nem sempre dava certo....

A manutenção de softwares é o maior pesadelo de um programador quando o código parece um campo minado

Existe muitos programadores que escrevem algoritmos mal planejados. Essa falta de planejamento dificulta a manutenção do aplicativo e aumenta a probabilidade de novos bugs.

VPN Rede virtual privada

A VPN permite a transferência de dados de modo privado e seguro em uma rede pública sem a utilização de infraestrutura adicional.

Direitos autorais

Os direitos autorais são garantidos para qualquer obra intelectual originadas do estado de espírito do autor ainda mesmo no período de desenvolvimento.

Algoritmo

O algoritmo é um conjunto de instruções escritas por um programador com intuito de solucionar um problema ou obter um resultado previsto.

Prevenção de colisões (collision avoidance)

Comportamento usado em steering behaviors para evitar que o agente se choque contra obstáculos durante o percurso do seu trajeto.