Use duration rather than frame counts. Stops false detection of being "stuck" with high frame rates (e.g. indoors).

actorid
cc9cii 11 years ago
parent c9f9566623
commit f597d3e88b

@ -18,9 +18,10 @@
namespace MWMechanics namespace MWMechanics
{ {
// NOTE: determined empirically but probably need further tweaking // NOTE: determined empirically but probably need further tweaking
static const int COUNT_BEFORE_STUCK = 20;
static const int COUNT_BEFORE_RESET = 200; static const int COUNT_BEFORE_RESET = 200;
static const int COUNT_EVADE = 7; static const float DIST_SAME_SPOT = 1.8f;
static const float DURATION_SAME_SPOT = 1.0f;
static const float DURATION_TO_EVADE = 0.4f;
AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat): AiWander::AiWander(int distance, int duration, int timeOfDay, const std::vector<int>& idle, bool repeat):
mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat) mDistance(distance), mDuration(duration), mTimeOfDay(timeOfDay), mIdle(idle), mRepeat(repeat)
@ -35,7 +36,8 @@ namespace MWMechanics
, mPrevY(0) , mPrevY(0)
, mWalkState(State_Norm) , mWalkState(State_Norm)
, mStuckCount(0) , mStuckCount(0)
, mEvadeCount(0) , mEvadeDuration(0)
, mStuckDuration(0)
, mSaidGreeting(false) , mSaidGreeting(false)
{ {
for(unsigned short counter = 0; counter < mIdle.size(); counter++) for(unsigned short counter = 0; counter < mIdle.size(); counter++)
@ -325,15 +327,21 @@ namespace MWMechanics
} }
else else
{ {
/* 1 n /* f t
* State_Norm <---> State_CheckStuck --> State_Evade * State_Norm <---> State_CheckStuck --> State_Evade
* ^ ^ | ^ | ^ | | * ^ ^ | ^ | ^ | |
* | | | | | | | | * | | | | | | | |
* | +---+ +---+ +---+ | m * | +---+ +---+ +---+ | u
* | any < n < m | * | any < t < u |
* +--------------------------------------------+ * +--------------------------------------------+
*
* f = one frame
* t = how long before considered stuck
* u = how long to move sideways
*/ */
bool samePosition = (abs(pos.pos[0] - mPrevX) < 1) && (abs(pos.pos[1] - mPrevY) < 1); bool samePosition = (abs(pos.pos[0] - mPrevX) < DIST_SAME_SPOT) &&
(abs(pos.pos[1] - mPrevY) < DIST_SAME_SPOT);
switch(mWalkState) switch(mWalkState)
{ {
case State_Norm: case State_Norm:
@ -349,30 +357,33 @@ namespace MWMechanics
if(!samePosition) if(!samePosition)
{ {
mWalkState = State_Norm; mWalkState = State_Norm;
// to do this properly need yet another variable, simply don't clear for now mStuckDuration = 0;
//mStuckCount = 0;
break; break;
} }
else else
{ {
// consider stuck only if position unchanges consecutively mStuckDuration += duration;
if((mStuckCount++ % COUNT_BEFORE_STUCK) == 0) // consider stuck only if position unchanges for a period
if(mStuckDuration > DURATION_SAME_SPOT)
{
mWalkState = State_Evade; mWalkState = State_Evade;
// NOTE: mStuckCount is purposely not cleared here mStuckDuration = 0;
mStuckCount++;
}
else else
break; // still in the same state, but counter got incremented break; // still in the same state, but duration added to timer
} }
} }
/* FALL THROUGH */ /* FALL THROUGH */
case State_Evade: case State_Evade:
{ {
if(mEvadeCount++ < COUNT_EVADE) mEvadeDuration += duration;
if(mEvadeDuration < DURATION_TO_EVADE)
break; break;
else else
{ {
mWalkState = State_Norm; // tried to evade, assume all is ok and start again mWalkState = State_Norm; // tried to evade, assume all is ok and start again
// NOTE: mStuckCount is purposely not cleared here mEvadeDuration = 0;
mEvadeCount = 0;
} }
} }
/* NO DEFAULT CASE */ /* NO DEFAULT CASE */

@ -58,7 +58,8 @@ namespace MWMechanics
WalkState mWalkState; WalkState mWalkState;
int mStuckCount; int mStuckCount;
int mEvadeCount; float mStuckDuration;
float mEvadeDuration;
bool mStoredAvailableNodes; bool mStoredAvailableNodes;
bool mChooseAction; bool mChooseAction;

Loading…
Cancel
Save