1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-07 03:12:36 +01:00

Connected animation translation to Character movement

This commit is contained in:
Daniel Evans 2014-03-02 10:38:50 +00:00
parent 411b913025
commit f289b6d0b0
7 changed files with 122 additions and 55 deletions

View File

@ -45,6 +45,9 @@ public:
*/ */
void setAnimation(Animation* animation, bool repeat = true); void setAnimation(Animation* animation, bool repeat = true);
Animation* getAnimation() const
{ return animation; }
void setModel(Model* model); void setModel(Model* model);
/** /**

View File

@ -10,6 +10,27 @@
class GTAVehicle; class GTAVehicle;
class GameWorld; class GameWorld;
struct AnimationGroup
{
Animation* idle;
Animation* walk;
Animation* walk_start;
Animation* run;
Animation* jump_start;
Animation* jump_glide;
Animation* jump_land;
Animation* car_sit;
Animation* car_sit_low;
AnimationGroup()
: idle(nullptr), walk(nullptr), walk_start(nullptr), run(nullptr),
jump_start(nullptr), jump_glide(nullptr), jump_land(nullptr),
car_sit(nullptr), car_sit_low(nullptr)
{}
};
/** /**
* @brief The GTACharacter struct * @brief The GTACharacter struct
* Stores data relating to an instance of a "pedestrian". * Stores data relating to an instance of a "pedestrian".
@ -48,6 +69,8 @@ public:
GTAAIController* controller; GTAAIController* controller;
AnimationGroup animations;
/** /**
* @brief GTACharacter Constructs a Character * @brief GTACharacter Constructs a Character
* @param pos * @param pos
@ -63,7 +86,7 @@ public:
Activity currentActivity; Activity currentActivity;
void changeAction(Activity newAction); void enterActivity(Activity act);
void tick(float dt); void tick(float dt);

View File

@ -13,14 +13,14 @@ void GTADefaultAIController::update(float dt)
else { else {
getUpTime -= dt; getUpTime -= dt;
if(getUpTime < 0.f) { if(getUpTime < 0.f) {
character->changeAction(GTACharacter::GettingUp); character->enterActivity(GTACharacter::GettingUp);
getUpTime = -1.f; getUpTime = -1.f;
} }
} }
} }
else if (character->currentActivity == GTACharacter::GettingUp ) { else if (character->currentActivity == GTACharacter::GettingUp ) {
if( character->animator->isCompleted() ) { if( character->animator->isCompleted() ) {
character->changeAction(GTACharacter::Idle); character->enterActivity(GTACharacter::Idle);
} }
} }
else { else {
@ -43,10 +43,10 @@ void GTADefaultAIController::update(float dt)
} }
if( targetNode == nullptr ) { if( targetNode == nullptr ) {
character->changeAction(GTACharacter::Idle); character->enterActivity(GTACharacter::Idle);
} }
else { else {
character->changeAction(GTACharacter::Walk); character->enterActivity(GTACharacter::Walk);
// Choose a new random margin // Choose a new random margin
if(character->getCurrentVehicle()) { if(character->getCurrentVehicle()) {
std::uniform_real_distribution<float> dist(2.f, 2.5f); std::uniform_real_distribution<float> dist(2.f, 2.5f);
@ -71,14 +71,14 @@ void GTADefaultAIController::update(float dt)
} }
else { else {
targetNode = nullptr; targetNode = nullptr;
character->changeAction(GTACharacter::Idle); character->enterActivity(GTACharacter::Idle);
} }
} }
else else
{ {
// Ensure the AI doesn't get stuck in idle with a target node. // Ensure the AI doesn't get stuck in idle with a target node.
if(character->currentActivity == GTACharacter::Idle) { if(character->currentActivity == GTACharacter::Idle) {
character->changeAction(GTACharacter::Walk); character->enterActivity(GTACharacter::Walk);
} }
} }
} }

View File

@ -65,10 +65,10 @@ void GTAPlayerAIController::update(float dt)
if( character->currentActivity != GTACharacter::Jump ) if( character->currentActivity != GTACharacter::Jump )
{ {
if( glm::length(direction) > 0.001f ) { if( glm::length(direction) > 0.001f ) {
character->changeAction(running ? GTACharacter::Run : GTACharacter::Walk); character->enterActivity(running ? GTACharacter::Run : GTACharacter::Walk);
} }
else { else {
character->changeAction(GTACharacter::Idle); character->enterActivity(GTACharacter::Idle);
} }
if( character->getCurrentVehicle() ) { if( character->getCurrentVehicle() ) {
@ -90,7 +90,6 @@ glm::vec3 GTAPlayerAIController::getTargetPosition()
void GTAPlayerAIController::jump() void GTAPlayerAIController::jump()
{ {
character->changeAction(GTACharacter::Jump);
character->jump(); character->jump();
} }

View File

@ -13,6 +13,7 @@ Animator::Animator()
void Animator::reset() void Animator::reset()
{ {
time = 0.f; time = 0.f;
serverTime = 0.f;
lastServerTime= 0.f; lastServerTime= 0.f;
if(model && animation) { if(model && animation) {
@ -56,7 +57,19 @@ void Animator::tick(float dt)
glm::vec3 Animator::getRootTranslation() const glm::vec3 Animator::getRootTranslation() const
{ {
if( model && model->rootFrameIdx != -1 ) { // This is a pretty poor assumption.
if(model->frames[model->rootFrameIdx]->getChildren().size() > 0) {
ModelFrame* realRoot = model->frames[model->rootFrameIdx]->getChildren()[0];
auto it = animation->bones.find(realRoot->getName());
if(it != animation->bones.end()) {
float df = fmod(lastServerTime, this->animation->duration);
float rt = getAnimationTime();
if(df < rt) {
auto lastKF = it->second->getInterpolatedKeyframe(df);
auto KF = it->second->getInterpolatedKeyframe(rt);
return KF.position - lastKF.position;
}
}
} }
return glm::vec3(); return glm::vec3();
@ -73,7 +86,7 @@ glm::mat4 Animator::getFrameMatrix(ModelFrame* frame, float alpha) const
if(it != animation->bones.end()) { if(it != animation->bones.end()) {
auto kf = it->second->getInterpolatedKeyframe(getAnimationTime(alpha)); auto kf = it->second->getInterpolatedKeyframe(getAnimationTime(alpha));
glm::mat4 m; glm::mat4 m;
if(it->second->type == AnimationBone::R00) { if(it->second->type == AnimationBone::R00 || frame->getName() == "swaist") {
m = glm::translate(m, frame->getDefaultTranslation()); m = glm::translate(m, frame->getDefaultTranslation());
m = m * glm::mat4_cast(kf.rotation); m = m * glm::mat4_cast(kf.rotation);
} }

View File

@ -11,12 +11,26 @@ GTACharacter::GTACharacter(GameWorld* engine, const glm::vec3& pos, const glm::q
controller(nullptr), currentActivity(None) controller(nullptr), currentActivity(None)
{ {
mHealth = 100.f; mHealth = 100.f;
// TODO move AnimationGroup creation somewhere else.
animations.idle = engine->gameData.animations["idle_stance"];
animations.walk = engine->gameData.animations["walk_player"];
animations.walk_start = engine->gameData.animations["walk_start"];
animations.run = engine->gameData.animations["run_player"];
animations.jump_start = engine->gameData.animations["jump_launch"];
animations.jump_glide = engine->gameData.animations["jump_glide"];
animations.jump_land = engine->gameData.animations["jump_land"];
animations.car_sit = engine->gameData.animations["car_sit"];
animations.car_sit_low = engine->gameData.animations["car_lsit"];
if(model) { if(model) {
animator = new Animator(); animator = new Animator();
animator->setModel(model); animator->setModel(model);
createActor(); createActor();
changeAction(Idle); enterActivity(Idle);
} }
} }
@ -25,6 +39,13 @@ GTACharacter::~GTACharacter()
destroyActor(); destroyActor();
} }
void GTACharacter::enterActivity(GTACharacter::Activity act)
{
if(currentActivity != act) {
currentActivity = act;
}
}
void GTACharacter::createActor(const glm::vec3& size) void GTACharacter::createActor(const glm::vec3& size)
{ {
if(physCharacter) { if(physCharacter) {
@ -64,49 +85,56 @@ void GTACharacter::destroyActor()
} }
} }
void GTACharacter::changeAction(Activity newAction)
{
if(currentActivity != newAction) {
currentActivity = newAction;
if(currentVehicle == nullptr) {
switch( currentActivity ) {
default:
case Idle:
animator->setAnimation(engine->gameData.animations.at("idle_stance"));
break;
case Walk:
animator->setAnimation(engine->gameData.animations.at("walk_civi"));
break;
case Run:
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;
}
}
else {
animator->setAnimation(engine->gameData.animations.at("car_sit"));
}
}
}
void GTACharacter::tick(float dt) void GTACharacter::tick(float dt)
{ {
if(controller) { if(controller) {
controller->update(dt); controller->update(dt);
} }
if(currentVehicle) {
enterActivity(VehicleSit);
}
switch(currentActivity) {
case Idle: {
if(animator->getAnimation() != animations.idle) {
animator->setAnimation(animations.idle);
}
} break;
case Walk: {
if(animator->getAnimation() != animations.walk) {
if(animator->getAnimation() != animations.walk_start) {
animator->setAnimation(animations.walk_start, false);
}
else if(animator->isCompleted()) {
animator->setAnimation(animations.walk);
}
}
} break;
case Run: {
if(animator->getAnimation() != animations.run) {
animator->setAnimation(animations.run);
}
} break;
case Jump: {
if(animator->getAnimation() != animations.jump_start) {
if(animator->getAnimation() != animations.jump_glide) {
animator->setAnimation(animations.jump_start, false);
}
else if(animator->isCompleted()) {
animator->setAnimation(animations.jump_glide);
}
}
} break;
case VehicleSit: {
if(animator->getAnimation() != animations.car_sit) {
animator->setAnimation(animations.car_sit);
}
} break;
default: break;
};
animator->tick(dt); animator->tick(dt);
updateCharacter(); updateCharacter();
@ -153,7 +181,7 @@ void GTACharacter::updateCharacter()
if(object->type() == Vehicle) { if(object->type() == Vehicle) {
GTAVehicle* vehicle = static_cast<GTAVehicle*>(object); GTAVehicle* vehicle = static_cast<GTAVehicle*>(object);
if(vehicle->physBody->getLinearVelocity().length() > 0.1f) { if(vehicle->physBody->getLinearVelocity().length() > 0.1f) {
changeAction(KnockedDown); enterActivity(KnockedDown);
} }
} }
} }
@ -166,7 +194,7 @@ void GTACharacter::updateCharacter()
{ {
if(physCharacter->onGround()) if(physCharacter->onGround())
{ {
changeAction(GTACharacter::Idle); enterActivity(GTACharacter::Idle);
} }
} }
else else
@ -211,6 +239,7 @@ bool GTACharacter::enterVehicle(GTAVehicle* vehicle, size_t seat)
enterVehicle(nullptr, 0); enterVehicle(nullptr, 0);
vehicle->setOccupant(seat, this); vehicle->setOccupant(seat, this);
setCurrentVehicle(vehicle, seat); setCurrentVehicle(vehicle, seat);
enterActivity(VehicleSit);
return true; return true;
} }
} }
@ -257,7 +286,7 @@ bool GTACharacter::takeDamage(const GameObject::DamageInfo& dmg)
void GTACharacter::jump() void GTACharacter::jump()
{ {
physCharacter->jump(); physCharacter->jump();
changeAction(GTACharacter::Jump); enterActivity(GTACharacter::Jump);
} }
void GTACharacter::resetToAINode() void GTACharacter::resetToAINode()

View File

@ -148,7 +148,7 @@ std::map<std::string, std::function<void (std::string)>> Commands = {
{"knock-down", {"knock-down",
[&](std::string) { [&](std::string) {
for(auto it = gta->pedestrians.begin(); it != gta->pedestrians.end(); ++it) { for(auto it = gta->pedestrians.begin(); it != gta->pedestrians.end(); ++it) {
(*it)->changeAction(GTACharacter::KnockedDown); (*it)->enterActivity(GTACharacter::KnockedDown);
} }
} }
}, },