diff --git a/framework2/Animator.cpp b/framework2/Animator.cpp index 55851047..2a7f6ab3 100644 --- a/framework2/Animator.cpp +++ b/framework2/Animator.cpp @@ -181,3 +181,8 @@ glm::mat4 Animator::getFrameMatrix(size_t frame) const } } } + +bool Animator::isCompleted() const +{ + return serverTime >= animation->duration; +} \ No newline at end of file diff --git a/framework2/GTACharacter.cpp b/framework2/GTACharacter.cpp index d560156a..83886d12 100644 --- a/framework2/GTACharacter.cpp +++ b/framework2/GTACharacter.cpp @@ -68,22 +68,25 @@ void GTACharacter::changeAction(Activity newAction) switch( currentActivity ) { default: case Idle: - createActor(); animator->setAnimation(engine->gameData.animations.at("idle_stance")); break; case Walk: - createActor(); animator->setAnimation(engine->gameData.animations.at("walk_civi")); break; case Run: - createActor(); animator->setAnimation(engine->gameData.animations.at("run_civi")); break; case KnockedDown: // Change body shape. + position += glm::vec3(0.f, 0.f, 0.5f); createActor(glm::vec3(0.5f, 0.5f, 0.1f)); animator->setAnimation(engine->gameData.animations.at("kd_front"), false); break; + case GettingUp: + // Change body shape back to normal. + createActor(); + animator->setAnimation(engine->gameData.animations.at("getup"), false); + break; case VehicleDrive: animator->setAnimation(engine->gameData.animations.at("car_sit")); break; diff --git a/framework2/GTADefaultAIController.cpp b/framework2/GTADefaultAIController.cpp index cfc318e7..596c8714 100644 --- a/framework2/GTADefaultAIController.cpp +++ b/framework2/GTADefaultAIController.cpp @@ -1,102 +1,129 @@ #include "renderwure/ai/GTADefaultAIController.hpp" #include #include +#include #include void GTADefaultAIController::update(float dt) { - if( action == Wander ) { - if( targetNode == nullptr ) { - GTAAINode::NodeType currentType = character->getCurrentVehicle() - ? GTAAINode::Vehicle : GTAAINode::Pedestrian; - - float d = std::numeric_limits< float >::max(); - for( auto n = character->engine->aigraph.nodes.begin(); - n != character->engine->aigraph.nodes.end(); - ++n ) { - if( (*n)->type != currentType ) continue; - if( (*n) == lastNode ) continue; - float ld = glm::length( (*n)->position - character->getPosition() ); - if( ld > nodeMargin && ld < d ) { - d = ld; - targetNode = (*n); - } - } - - if( targetNode == nullptr ) { - character->changeAction(GTACharacter::Idle); - } - else { - character->changeAction(GTACharacter::Walk); - // Choose a new random margin - if(character->getCurrentVehicle()) { - std::uniform_real_distribution dist(2.f, 2.5f); - nodeMargin = dist(character->engine->randomEngine); - } - else { - std::uniform_real_distribution dist(1.f, 1.5f); - nodeMargin = dist(character->engine->randomEngine); - } - } + if( character->currentActivity == GTACharacter::KnockedDown ) { + if( getUpTime < 0.f ) { + getUpTime = 1.5f; } - else if( glm::length(getTargetPosition() - character->getPosition()) < nodeMargin ) { - if(targetNode->connections.size() > 0) { - std::uniform_int_distribution uniform(0, targetNode->connections.size()-1); - GTAAINode* nextNode = nullptr; size_t i = 0; - do - { - nextNode = targetNode->connections[uniform(character->engine->randomEngine)]; - } while(i++ < targetNode->connections.size() && nextNode == lastNode); - lastNode = targetNode; - targetNode = nextNode; - } - else { - targetNode = nullptr; - character->changeAction(GTACharacter::Idle); + else { + getUpTime -= dt; + if(getUpTime < 0.f) { + character->changeAction(GTACharacter::GettingUp); + getUpTime = -1.f; } } } + else if (character->currentActivity == GTACharacter::GettingUp ) { + if( character->animator->isCompleted() ) { + character->changeAction(GTACharacter::Idle); + } + } + else { + if( action == Wander ) { + if( targetNode == nullptr ) { + GTAAINode::NodeType currentType = character->getCurrentVehicle() + ? GTAAINode::Vehicle : GTAAINode::Pedestrian; - if( action == Wander && targetNode != nullptr ) { - auto d = targetNode->position - character->getPosition(); + float d = std::numeric_limits< float >::max(); + for( auto n = character->engine->aigraph.nodes.begin(); + n != character->engine->aigraph.nodes.end(); + ++n ) { + if( (*n)->type != currentType ) continue; + if( (*n) == lastNode ) continue; + float ld = glm::length( (*n)->position - character->getPosition() ); + if( ld > nodeMargin && ld < d ) { + d = ld; + targetNode = (*n); + } + } + + if( targetNode == nullptr ) { + character->changeAction(GTACharacter::Idle); + } + else { + character->changeAction(GTACharacter::Walk); + // Choose a new random margin + if(character->getCurrentVehicle()) { + std::uniform_real_distribution dist(2.f, 2.5f); + nodeMargin = dist(character->engine->randomEngine); + } + else { + std::uniform_real_distribution dist(1.f, 1.5f); + nodeMargin = dist(character->engine->randomEngine); + } + } + } + else if( glm::length(getTargetPosition() - character->getPosition()) < nodeMargin ) { + if(targetNode->connections.size() > 0) { + std::uniform_int_distribution uniform(0, targetNode->connections.size()-1); + GTAAINode* nextNode = nullptr; size_t i = 0; + do + { + nextNode = targetNode->connections[uniform(character->engine->randomEngine)]; + } while(i++ < targetNode->connections.size() && nextNode == lastNode); + lastNode = targetNode; + targetNode = nextNode; + } + else { + targetNode = nullptr; + character->changeAction(GTACharacter::Idle); + } + } + else + { + // Ensure the AI doesn't get stuck in idle with a target node. + if(character->currentActivity == GTACharacter::Idle) { + character->changeAction(GTACharacter::Walk); + } + } + } - if(lastNode && character->getCurrentVehicle()) { - auto nDir = glm::normalize(targetNode->position - lastNode->position); - auto right = glm::cross(nDir, glm::vec3(0.f, 0.f, 1.f)); - d += right * 2.2f; + if( action == Wander && targetNode != nullptr ) { + auto d = targetNode->position - character->getPosition(); + + if(lastNode && character->getCurrentVehicle()) { + auto nDir = glm::normalize(targetNode->position - lastNode->position); + auto right = glm::cross(nDir, glm::vec3(0.f, 0.f, 1.f)); + d += right * 2.2f; + } + + if(character->getCurrentVehicle()) { + auto vd = glm::inverse(character->getCurrentVehicle()->getRotation()) * d; + float va = -atan2( vd.x, vd.y ); + if(glm::abs(va) > (3.141f/2.f)) { + va = -va; + } + character->getCurrentVehicle()->setSteeringAngle(va); + } + else { + float a = -atan2( d.x, d.y ); + character->rotation = glm::quat(glm::vec3(0.f, 0.f, a)); + } } if(character->getCurrentVehicle()) { - auto vd = glm::inverse(character->getCurrentVehicle()->getRotation()) * d; - float va = -atan2( vd.x, vd.y ); - if(glm::abs(va) > (3.141f/2.f)) { - va = -va; + if(targetNode == nullptr) { + character->getCurrentVehicle()->setThrottle(0.f); } - character->getCurrentVehicle()->setSteeringAngle(va); - } - else { - float a = -atan2( d.x, d.y ); - character->rotation = glm::quat(glm::vec3(0.f, 0.f, a)); - } - } + else { + float targetVelocity = 5.f; + float perc = (targetVelocity - character->getCurrentVehicle()->physBody->getLinearVelocity().length())/targetVelocity; + perc = std::min(1.f, std::max(0.f, perc)); - if(character->getCurrentVehicle()) { - if(targetNode == nullptr) { - character->getCurrentVehicle()->setThrottle(0.f); - } - else { - float targetVelocity = 5.f; - float perc = (targetVelocity - character->getCurrentVehicle()->physBody->getLinearVelocity().length())/targetVelocity; - perc = std::min(1.f, std::max(0.f, perc)); + // Determine if the vehicle should reverse instead. + auto td = getTargetPosition() - character->getPosition(); + auto vd = character->getCurrentVehicle()->getRotation() * glm::vec3(0.f, 1.f, 0.f); + if(glm::dot(td, vd) < -0.25f) { + perc *= -1.f; + } - // Determine if the vehicle should reverse instead. - auto td = getTargetPosition() - character->getPosition(); - auto vd = character->getCurrentVehicle()->getRotation() * glm::vec3(0.f, 1.f, 0.f); - if(glm::dot(td, vd) < -0.25f) { - perc *= -1.f; + character->getCurrentVehicle()->setThrottle(perc); } - - character->getCurrentVehicle()->setThrottle(perc); } } } diff --git a/framework2/include/renderwure/ai/GTADefaultAIController.hpp b/framework2/include/renderwure/ai/GTADefaultAIController.hpp index 7a1db5ab..a7d1531b 100644 --- a/framework2/include/renderwure/ai/GTADefaultAIController.hpp +++ b/framework2/include/renderwure/ai/GTADefaultAIController.hpp @@ -18,6 +18,7 @@ class GTADefaultAIController : public GTAAIController GTAAINode* lastNode; float nodeMargin; /// Minimum distance away to "reach" node. + float getUpTime; /// Time to wait before getting up. public: @@ -26,7 +27,7 @@ public: action(Wander), targetNode(nullptr), lastNode(nullptr), - nodeMargin(0.f) {} + nodeMargin(0.f), getUpTime(-1.f) {} void update(float dt); diff --git a/framework2/include/renderwure/engine/Animator.hpp b/framework2/include/renderwure/engine/Animator.hpp index 867a7a7d..8d5ea793 100644 --- a/framework2/include/renderwure/engine/Animator.hpp +++ b/framework2/include/renderwure/engine/Animator.hpp @@ -80,6 +80,11 @@ public: * @return */ glm::mat4 getFrameMatrix(size_t frame) const; + + /** + * Returns true if the animation has finished playing. + */ + bool isCompleted() const; }; #endif diff --git a/framework2/include/renderwure/objects/GTACharacter.hpp b/framework2/include/renderwure/objects/GTACharacter.hpp index 641458fd..73bbe69c 100644 --- a/framework2/include/renderwure/objects/GTACharacter.hpp +++ b/framework2/include/renderwure/objects/GTACharacter.hpp @@ -31,7 +31,8 @@ public: Crouch, VehicleDrive, VehicleSit, - KnockedDown + KnockedDown, + GettingUp }; std::shared_ptr ped; diff --git a/viewer/main.cpp b/viewer/main.cpp index a751e07f..6fb09e10 100644 --- a/viewer/main.cpp +++ b/viewer/main.cpp @@ -86,6 +86,11 @@ void command(const std::string& line) playerCharacter = gta->createPedestrian(1, plyPos); player = new GTAPlayerAIController(playerCharacter); } + else if("knock-down" == cmd) { + for(auto it = gta->pedestrians.begin(); it != gta->pedestrians.end(); ++it) { + (*it)->changeAction(GTACharacter::KnockedDown); + } + } else if("list-ipl" == cmd) { for(std::map::iterator it = gta->gameData.iplLocations.begin(); it != gta->gameData.iplLocations.end(); @@ -341,7 +346,7 @@ void update(float dt) gta->vehicleInstances[v]->tick(dt); } - gta->dynamicsWorld->stepSimulation(dt, 1, dt); + gta->dynamicsWorld->stepSimulation(dt, 2, dt); } } @@ -475,7 +480,7 @@ int main(int argc, char *argv[]) sf::Clock clock; float accum = 0.f; - float ts = 1.f / 20.f; + float ts = 1.f / 60.f; while (window.isOpen()) { sf::Event event;