1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-09 12:22:34 +01:00

Initial Traffic wandering algorithm (pedestrians only)

This commit is contained in:
Daniel Evans 2015-02-26 01:15:17 +00:00
parent fe4926e5d6
commit 7f2c5a4645
4 changed files with 61 additions and 7 deletions

View File

@ -5,6 +5,7 @@
#include <glm/gtc/quaternion.hpp>
#include <string>
struct AIGraphNode;
class CharacterObject;
class VehicleObject;
@ -40,7 +41,11 @@ public:
/**
* Keep close to leader character
*/
FollowLeader
FollowLeader,
/**
* Wander randomly around the map
*/
TrafficWander
};
protected:
@ -65,6 +70,7 @@ protected:
// Goal related variables
Goal currentGoal;
CharacterObject* leader;
AIGraphNode* targetNode;
public:

View File

@ -28,7 +28,7 @@ void CharacterController::setActivity(CharacterController::Activity* activity)
CharacterController::CharacterController(CharacterObject* character)
: character(character), _currentActivity(nullptr), _nextActivity(nullptr), running(false),
vehicleIdle(0.f), currentGoal(None), leader(nullptr)
vehicleIdle(0.f), currentGoal(None), leader(nullptr), targetNode(nullptr)
{
character->controller = this;
}

View File

@ -55,6 +55,45 @@ void DefaultAIController::update(float dt)
}
}
break;
case TrafficWander:
{
if( targetNode )
{
auto targetDistance = glm::vec2(character->getPosition() - targetNode->position);
if( glm::length(targetDistance) <= 0.1f )
{
// Assign the next target node
auto lastTarget = targetNode;
std::random_device rd;
std::default_random_engine re(rd());
std::uniform_int_distribution<> d(0, lastTarget->connections.size()-1);
targetNode = lastTarget->connections.at(d(re));
setNextActivity(new Activities::GoTo(targetNode->position));
}
else if ( getCurrentActivity() == nullptr )
{
setNextActivity(new Activities::GoTo(targetNode->position));
}
}
else
{
// We need to pick an initial node
auto& graph = getCharacter()->engine->aigraph;
AIGraphNode* node = nullptr;
float mindist = std::numeric_limits<float>::max();
for( auto n : graph.nodes )
{
float d = glm::distance( n->position, getCharacter()->getPosition() );
if( d < mindist )
{
node = n;
mindist = d;
}
}
targetNode = node;
}
}
break;
default: break;
}

View File

@ -1,5 +1,6 @@
#include "ai/TrafficDirector.hpp"
#include <ai/AIGraphNode.hpp>
#include <ai/CharacterController.hpp>
#include <engine/GameWorld.hpp>
#include <engine/GameObject.hpp>
#include <objects/CharacterObject.hpp>
@ -18,8 +19,8 @@ std::vector< AIGraphNode* > TrafficDirector::findAvailableNodes(AIGraphNode::Nod
for ( AIGraphNode* node : graph->nodes )
{
if ( node->type != type ) continue;
if ( ! node->external ) continue;
if ( node->type != type ) continue;
if ( glm::distance( near, node->position ) < radius )
{
available.push_back( node );
@ -75,6 +76,13 @@ std::vector<GameObject*> TrafficDirector::populateNearby(const glm::vec3& center
auto type = AIGraphNode::Pedestrian;
auto available = findAvailableNodes(type, center, radius);
/// Hardcoded cop Pedestrian
std::vector<uint16_t> validPeds = { 1 };
validPeds.insert(validPeds.end(), {20, 11, 19, 5});
std::random_device rd;
std::default_random_engine re(rd());
std::uniform_int_distribution<> d(0, validPeds.size()-1);
for ( AIGraphNode* spawn : available )
{
if ( maxPopulation > -1 )
@ -86,10 +94,11 @@ std::vector<GameObject*> TrafficDirector::populateNearby(const glm::vec3& center
maxPopulation --;
}
// spawn a cop
auto cop = world->createPedestrian(1, spawn->position + glm::vec3( 0.f, 0.f, 1.f ) );
cop->setLifetime(GameObject::TrafficLifetime);
created.push_back( cop );
// Spawn a pedestrian from the available pool
auto ped = world->createPedestrian(validPeds[d(re)], spawn->position + glm::vec3( 0.f, 0.f, 1.f ) );
ped->setLifetime(GameObject::TrafficLifetime);
ped->controller->setGoal(CharacterController::TrafficWander);
created.push_back( ped );
}
// Find places it's legal to spawn things