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:
parent
411b913025
commit
f289b6d0b0
@ -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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user