Steering Behaviors – Wander
Wander é o Steering Behavior que faz com que um agente passeie aleatoriamente. O algoritmo cria um “alvo”, que é para onde o agente se locomove. Esse alvo desloca-se aleatoriamente sobre um círculo, projetado na frente do agente. O grau de aleatoriedade do movimento do alvo sobre o círculo é chamado jitter. Toda esse complicação é feita para garantir um movimento suave.

A implementação desse algoritmo, no livro do Buckland, envolvia a função “PointToWorldSpace”, que segundo o autor “sua descrição está fora do escopo do livro”. Estudando um pouco a teoria de sistemas de coordenadas, vi que uma função dessas certamente será necessária futuramente para a SofiaIA. Mas não vou entrar no mérito de multiplicações de matrizes por enquanto.
A idéia da função era clara. Projetar o alvo para frente do veículo. Se assumirmos que o raio do alvo, distância e jitter já se encontram no sistema de coordenadas do mundo, então projetar o alvo para frente do veículo torna-se uma tarefa fácil.
Abaixo, o algoritmo implementado com esses pressupostos:
namespace behavior {
class Wander : public SteerForce
{
private:
const Vehicle& vehicle;
const double distance;
const double radius;
const double jitter;
math::Vector2D target;
public:
Wander(const Vehicle& wanderVehicle, double wanderDistance,
double wanderRadius, double wanderJitter)
: vehicle(wanderVehicle), distance(wanderDistance),
radius(wanderRadius), jitter(wanderJitter)
{
srand ( time(NULL) );
}
//Returns a random number between -1 and 1
inline float randomClamped()
{
return (rand() / (RAND_MAX/2.0f))-1;
}
virtual math::Vector2D calculate()
{
//First, add a small random vector to the target's position
target += math::Vector2D(randomClamped() * jitter,
randomClamped() * jitter);
//reproject the target vector to the circle size
target.setSize(radius);
//move the target to the front of the vehicle
target += math::Vector2D(distance,0)
.rotate(vehicle.getVelocity().getAngle());
//In order to move the target to vehicle front, the next operation
//whould be summing the vehicle position, to the target position.
//But since to calculate the steering direction we needed to
//subtract the vehicle position, the two following lines:
// target += vehicle.position();
// return target - vehicle.position();
//where simplified just to:
return target;
}
};
}
Note que o wander não precisa de nenhum parâmetro de templates e, portanto, poderia ter sido implementado em dois arquivos (ao invés de só no .h). Esse algoritmo já foi corrigido e testado em meu protótipo e já funciona.