mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 02:12:45 +01:00
Connected animation translation to Character movement
This commit is contained in:
parent
411b913025
commit
f289b6d0b0
@ -45,6 +45,9 @@ public:
|
||||
*/
|
||||
void setAnimation(Animation* animation, bool repeat = true);
|
||||
|
||||
Animation* getAnimation() const
|
||||
{ return animation; }
|
||||
|
||||
void setModel(Model* model);
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,27 @@
|
||||
class GTAVehicle;
|
||||
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
|
||||
* Stores data relating to an instance of a "pedestrian".
|
||||
@ -48,6 +69,8 @@ public:
|
||||
|
||||
GTAAIController* controller;
|
||||
|
||||
AnimationGroup animations;
|
||||
|
||||
/**
|
||||
* @brief GTACharacter Constructs a Character
|
||||
* @param pos
|
||||
@ -63,7 +86,7 @@ public:
|
||||
|
||||
Activity currentActivity;
|
||||
|
||||
void changeAction(Activity newAction);
|
||||
void enterActivity(Activity act);
|
||||
|
||||
void tick(float dt);
|
||||
|
||||
|
@ -13,14 +13,14 @@ void GTADefaultAIController::update(float dt)
|
||||
else {
|
||||
getUpTime -= dt;
|
||||
if(getUpTime < 0.f) {
|
||||
character->changeAction(GTACharacter::GettingUp);
|
||||
character->enterActivity(GTACharacter::GettingUp);
|
||||
getUpTime = -1.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (character->currentActivity == GTACharacter::GettingUp ) {
|
||||
if( character->animator->isCompleted() ) {
|
||||
character->changeAction(GTACharacter::Idle);
|
||||
character->enterActivity(GTACharacter::Idle);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -43,10 +43,10 @@ void GTADefaultAIController::update(float dt)
|
||||
}
|
||||
|
||||
if( targetNode == nullptr ) {
|
||||
character->changeAction(GTACharacter::Idle);
|
||||
character->enterActivity(GTACharacter::Idle);
|
||||
}
|
||||
else {
|
||||
character->changeAction(GTACharacter::Walk);
|
||||
character->enterActivity(GTACharacter::Walk);
|
||||
// Choose a new random margin
|
||||
if(character->getCurrentVehicle()) {
|
||||
std::uniform_real_distribution<float> dist(2.f, 2.5f);
|
||||
@ -71,14 +71,14 @@ void GTADefaultAIController::update(float dt)
|
||||
}
|
||||
else {
|
||||
targetNode = nullptr;
|
||||
character->changeAction(GTACharacter::Idle);
|
||||
character->enterActivity(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);
|
||||
character->enterActivity(GTACharacter::Walk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ void GTAPlayerAIController::update(float dt)
|
||||
if( character->currentActivity != GTACharacter::Jump )
|
||||
{
|
||||
if( glm::length(direction) > 0.001f ) {
|
||||
character->changeAction(running ? GTACharacter::Run : GTACharacter::Walk);
|
||||
character->enterActivity(running ? GTACharacter::Run : GTACharacter::Walk);
|
||||
}
|
||||
else {
|
||||
character->changeAction(GTACharacter::Idle);
|
||||
character->enterActivity(GTACharacter::Idle);
|
||||
}
|
||||
|
||||
if( character->getCurrentVehicle() ) {
|
||||
@ -90,7 +90,6 @@ glm::vec3 GTAPlayerAIController::getTargetPosition()
|
||||
|
||||
void GTAPlayerAIController::jump()
|
||||
{
|
||||
character->changeAction(GTACharacter::Jump);
|
||||
character->jump();
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@ Animator::Animator()
|
||||
void Animator::reset()
|
||||
{
|
||||
time = 0.f;
|
||||
serverTime = 0.f;
|
||||
lastServerTime= 0.f;
|
||||
|
||||
if(model && animation) {
|
||||
@ -56,7 +57,19 @@ void Animator::tick(float dt)
|
||||
|
||||
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();
|
||||
@ -73,7 +86,7 @@ glm::mat4 Animator::getFrameMatrix(ModelFrame* frame, float alpha) const
|
||||
if(it != animation->bones.end()) {
|
||||
auto kf = it->second->getInterpolatedKeyframe(getAnimationTime(alpha));
|
||||
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 = m * glm::mat4_cast(kf.rotation);
|
||||
}
|
||||
|
@ -11,12 +11,26 @@ GTACharacter::GTACharacter(GameWorld* engine, const glm::vec3& pos, const glm::q
|
||||
controller(nullptr), currentActivity(None)
|
||||
{
|
||||
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) {
|
||||
animator = new Animator();
|
||||
animator->setModel(model);
|
||||
|
||||
createActor();
|
||||
changeAction(Idle);
|
||||
enterActivity(Idle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +39,13 @@ GTACharacter::~GTACharacter()
|
||||
destroyActor();
|
||||
}
|
||||
|
||||
void GTACharacter::enterActivity(GTACharacter::Activity act)
|
||||
{
|
||||
if(currentActivity != act) {
|
||||
currentActivity = act;
|
||||
}
|
||||
}
|
||||
|
||||
void GTACharacter::createActor(const glm::vec3& size)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(controller) {
|
||||
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);
|
||||
updateCharacter();
|
||||
|
||||
@ -153,7 +181,7 @@ void GTACharacter::updateCharacter()
|
||||
if(object->type() == Vehicle) {
|
||||
GTAVehicle* vehicle = static_cast<GTAVehicle*>(object);
|
||||
if(vehicle->physBody->getLinearVelocity().length() > 0.1f) {
|
||||
changeAction(KnockedDown);
|
||||
enterActivity(KnockedDown);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,7 +194,7 @@ void GTACharacter::updateCharacter()
|
||||
{
|
||||
if(physCharacter->onGround())
|
||||
{
|
||||
changeAction(GTACharacter::Idle);
|
||||
enterActivity(GTACharacter::Idle);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -211,6 +239,7 @@ bool GTACharacter::enterVehicle(GTAVehicle* vehicle, size_t seat)
|
||||
enterVehicle(nullptr, 0);
|
||||
vehicle->setOccupant(seat, this);
|
||||
setCurrentVehicle(vehicle, seat);
|
||||
enterActivity(VehicleSit);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -257,7 +286,7 @@ bool GTACharacter::takeDamage(const GameObject::DamageInfo& dmg)
|
||||
void GTACharacter::jump()
|
||||
{
|
||||
physCharacter->jump();
|
||||
changeAction(GTACharacter::Jump);
|
||||
enterActivity(GTACharacter::Jump);
|
||||
}
|
||||
|
||||
void GTACharacter::resetToAINode()
|
||||
|
@ -148,7 +148,7 @@ std::map<std::string, std::function<void (std::string)>> Commands = {
|
||||
{"knock-down",
|
||||
[&](std::string) {
|
||||
for(auto it = gta->pedestrians.begin(); it != gta->pedestrians.end(); ++it) {
|
||||
(*it)->changeAction(GTACharacter::KnockedDown);
|
||||
(*it)->enterActivity(GTACharacter::KnockedDown);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user