Я задал этот вопрос около получаса назад, но в коде были опечатки, и я был не очень ясен, поэтому я удалил и пытаюсь снова с лучшим форматом.
Я получаю ошибку сегментации в моем коде, проблема, кажется, заключается в вызове функции if( (*trans).test((*this), *(*itr)) )
внутри World::update()
:
void World::update(sf::Time dt)
{
mPlayer->setVelocity(0.f, 0.f);
while (!mCommandQueue.isEmpty()){
Command cmd = mCommandQueue.pop();
cmd.action(cmd.node, dt);
}
mSceneGraph.update(dt);
adaptPlayerPosition();
//Enemy Spawn engine
if (mSpawnTimer.getElapsedTime().asSeconds() >= SPAWN_INTERVAL && mEnemies.size() < MAX_NUM_ENEMIES){
float winX = mWindow.getDefaultView().getSize().x;
float winY = mWindow.getDefaultView().getSize().y;
float x = rand() % (int)winX;
float y = rand() % (int)winY;
spawnEnemy(x, y, EnemyType::Loner, IState::ILWander);
mSpawnTimer.restart();
}
// FSM update
IState::ID curEnemyStateID;
FState curEnemyState;
bool trigger = false;
ICondition triggeredtrans;
FState triggeredState;
for(auto itr = mEnemies.begin(); itr != mEnemies.end(); ++itr){
curEnemyStateID = (*itr)->getState();
// set curState to whatever the enemy's curState is
switch(curEnemyStateID){
case 0:
curEnemyState = LWander;
break;
default:
break;
}
auto tState = curEnemyState.getTransitionStates().begin();
for(auto trans = curEnemyState.getConditions().begin(); trans != curEnemyState.getConditions().end(); ++trans){
if( (*trans).test((*this), *(*itr)) ){
trigger = true;
triggeredState = (*tState);
break;
}
++tState;
}
if(trigger){
(*itr)->setState(IState::ILRushPlayer);
curEnemyState = LRushPlayer;
}
curEnemyState.getAction()->doAction((*this), *(*itr));
}
}
Контекст:
trans
является итератором для std::vector<ICondition> conditions
где каждый ICondition
имеет test(World& world, Enemy& enemy)
, itr
является итератором через std::vector<Enemy*>
что проводится World
,
conditions
вектор заполняется в этой функции:
void World::initializeStates()
{
Wander LWanderAction;
LWander.setAction(LWanderAction);
DistFromPlayer LWanderCond1(30);
LWander.pushCondition(LWanderCond1);
LWander.pushTransitionState(LRushPlayer);
}
LWander это государство (FState
) в моей машине конечных состояний. Wander
это класс, который наследует IAction
, а также setAction
принимает IAction
параметр: FState::setAction(IAction iact)
DistFromPlayer
это класс, который наследует ICondition
,
FState::pushCondition(ICondition icond)
а также FState::pushTransitionState(Fstate state)
следует принять их аргументы и подтолкнуть их к Fstate
«s conditions
а также states
векторы. (Состояние перехода и совпадающее целевое состояние должны иметь одинаковые индексы в обоих)
LWander
а также LRushPlayer
оба являются членами World
,
И это должно охватывать все. Я не знаю, почему я получаю SegFault, но я предполагаю, что проблема заключается в том, как все происходит в LWander
в World::initializeStates()
, Я должен также отметить, что SegFault происходит сразу после появления первого врага в моей игре, который также является тем же фреймом обновления, который работает (*trans).test(*this, **itr)
в первый раз. Все Enemy
начало в LWander
государство.
ICondition-х virtual bool test(World& world, Enemy& enemy);
определяется как:
bool ICondition::test(World& world, Enemy& enemy){
return false;
//returns false by default, overwritten later
}
и DistFromPlayer bool test(World& world, Enemy& enemy);
определяется как:
bool DistFromPlayer::test(World& world, Enemy& enemy)
{
std::cout << "DistFromPlayer (LWander's Transition) was reached\n";
return false;
}
и содержит только оператор печати для целей отладки.
Обратный след GDB
#0 World::update (this=0x6464408, dt=...) at C:\...\World.cpp:97
#1 0x0040416b in GameState::update (this=0x64643f0, dt=...) at C:\...\GameState.cpp:22
#2 0x00402435 in StateStack::update (this=0x28fde0, dt=...) at C:\...\StateStack.cpp:19
#3 0x00403782 in Game::update (this=0x28fbc0, elapsedTime=...) at C:\...\Game.cpp:58
#4 0x004036a2 in Game::run (this=0x28fbc0) at C:\...\Game.cpp:48
#5 0x0040888b in main () at C:\...\main.cpp:7
Я подозреваю tState итератор. Вы только инициализируете его с помощью begin () и увеличиваете его. Я не могу найти какой-либо тест против end () соответствующего контейнера. Или это безопасно из-за некоторой связи между curEnemyState.getTransitionStates () и curEnemyState.getConditions (), которую я не понимаю?
Других решений пока нет …