Sofia IA

Inteligência artificial para jogos

Steering Behaviors – Wander

fazer um comentário »

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.

Steering behavior - wander

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.

Escrito por vinigodoy

04 dUTC Fevereiro dUTC 2008 às 13:01:23

Deixe uma resposta