Машина состояний (комментарии)
Это сообщение сгенерировано автоматически.
"Событие(Event):
Для того же ящика события могут быть: толкнуть, столкнуться с землей, скатиться с опоры. События (Event) нужны для оповещения машины состояний, что с объектом что-то произошло. Если ящик лежит и его толкнули, то он покатиться. Это переход из состояния «лежать» в «катиться» по событию «толчок». "
Зачем нужен Event? Зачем нужно создавать Event и только потом включать нужное состояние? Почему сразу нельзя переключится в нужное состояние?
codesnip
Одно событие может включать разные состояния, в зависимости от текущего
> Почему сразу нельзя переключится в нужное состояние?
Инициатор события не знает в каком текущем состоянии находится объект. Он только шлет сообщение, что что-то случилось. Объект уже отрабатывает событие в том алгоритме, который ему задан.
Volodar
> Инициатор события не знает в каком текущем состоянии находится объект. Он
> только шлет сообщение, что что-то случилось. Объект уже отрабатывает событие в
> том алгоритме, который ему задан.
Так он может вызвать функцию у обьекта ВключитьСостояние(состояниеПадать). А как переключится в это состояние уже сам обьект решает.
С Event получается тоже самое. Только вместо того чтоб сразу вызвать функцию ВключитьСостояние(состояниеПадать), сохраняется в памяти Event. И потом через время вызывается функция ВключитьСостояние(состояниеПадать).
Получается что сущность Event лишняя.
Как раз нет. Посылая только одно-два события, происходит довольно сложное управление.
Конечно, с ящиком пример довольно прост. Для того и привел более сложный пример с пушкой. Она получает только два сообщения - capture, release target. Пушка уже сама разруливает, как ей отреагировать на события.
К примеру есть главный класс, управляющий пушками и врагами (жанр Tower Defense):
GameBoard::update(float dt) { for( auto tower : towers ) { target = find_target_for_tower( tower ); if( target ) tower->dispatch_event( capture, target ); if( !target ) tower->dispatch_event( release, target ); tower->update( dt ); } }
Пушка уже может в этот момент стрелять, перезаряжаться, улучшаться, вести подготовку к бою и т.д. GameBoard не знает обо всем этом и ему это не мешает.
Volodar
И что должен был показать этот кривой и глючный кусок кода?
GameBoard::update(float dt) { for( auto tower : towers ) { target = find_target_for_tower( tower ); if( target ) tower->Capture(target) else tower->Release(); tower->update( dt ); } }
Volodar
> for( auto tower : towers )
Если можно написать auto - пиши. Это с js такая мода пошла?
Volodar
А чем твоя реализация отличается от каноничной? Ну кроме того что она линейная.
Я конечно не эксперт по плюсам, но почему стейты не enum ?) Это же не безопасно.
Почему у тебя стейты владеют графом состояний, а не граф состоит из стейтов?
Также события как то стремно сделаны. Как писали выше, в них, в данном коде, нет никакого смысла.
int name - говнокод как не крути. Задефайни типы специальные хоть)
void Machine::dispatch_event( int name )
void Machine::setstate( int name )
State* Machine::getstate( int name )
Mephistopheles
Как раз enum. В первом листинге использовался простейший пример как показной, не стал усложнять без причины
Если можно поподробнее как у тебя происходит например переход "Подготовка-стрельба"?
DanielDem
Подготовка это состояние длительность N секунд. В это время может проигрываться анимация у пушки. После отведенного времени пушка посылает сама себе событие готовности, и переход в режим стрельбы.
За время подготовки она могла получить событие, что цель ушла (release target). Тогда она переходи в режим ожидания, что тоже, временное состояние. После нгео либо в режим огня по событию из вне, либо спать.
Т.е не управляется только извне, она вполне способна на самостоятельное переключение своих состояний. Но инициация всего этого происходит извне.
Т.е. сама "подготовка" у тебя состояние (пусть и какое то особенное)?
Вопрос:
Если пушка находится в состоянии "Ожидание", то чтобы стрелять по врагу, т.е. перевести в состояние "Режим огня" какое надо посылать событие: событие "Режим огня" или переходное событие "Подготовка к бою" которое по исполнению пошлёт событие "Режим огня" ?
Автор, а ты уверен что это FSM? По описанию это больше похоже на Behaviour Tree, только очень странное дерево.
Dampire
Хм, не встречал ранее этот термин. Почитал, да, это Behaviour Tree у меня описан. Но как понял, behaviour tree это сущность построенная на машине состояний, т.е. одна из ее реализаций. Спасибо за термин, буду знать.
DanielDem
А тут уже зависит от того, что надо получить в итоге. И на сколько интересной и сложной хочется получить систему.
Можно обойтись двумя состояниями - ведение огня и ожидание. Переход между ними по событиям "увидел цель", "потерял(убил) цель".
Можно добавить третье состояние - перезарядка. Добавляется 2 события - перезарядить, перезарядилось:
стрельба + перезарядить = перезарядка стрельба + не потеря цели = ожидание перезарядка + зарядилось = стрельба ожидание + вижу цель = стрельба
Я себе добавил еще несколько состояний, подготовка к бою, отдых от боя, если посмотреть видео, видно как у пушки перед стрельбой выдвигается лазер и когда цель уезжает - лазер прячется.
Тема в архиве.