More behavior tree generic nodes

This commit is contained in:
Nikita Lisitsa 2021-10-17 00:49:11 +03:00
parent b8d03d41a4
commit 6e4db713d3

View file

@ -183,6 +183,30 @@ namespace psemek::util
}
};
template <typename ActionFn>
struct action
{
ActionFn actionFn;
action(ActionFn actionFn)
: actionFn(std::move(actionFn))
{}
void start(Args ...)
{}
status update(Time, Args ... args)
{
actionFn(args...);
return finished{true};
}
bool event(Event const &)
{
return false;
}
};
template <typename TimeFn>
struct wait
{
@ -225,7 +249,7 @@ namespace psemek::util
void start(Args ...)
{}
status update(Time dt, Args ... args)
status update(Time, Args ... args)
{
return finished{condFn(args...)};
}
@ -454,6 +478,99 @@ namespace psemek::util
}
}
};
template <typename ... Children>
struct selector
{
std::tuple<Children...> children;
bool current_started = false;
size_t current = 0;
selector(Children ... children)
: children{std::move(children)...}
{}
void start(Args ...)
{
if constexpr (sizeof...(Children) == 0)
{
current = 1;
}
else
{
current = 0;
current_started = false;
}
}
status update(Time dt, Args ... args)
{
return update_impl<0>(dt, args...);
}
bool event(Event const & e)
{
return event_impl<0>(e);
}
private:
template <size_t I>
status update_impl(Time dt, Args ... args)
{
if constexpr (I == sizeof...(Children))
{
return finished{false};
}
else
{
if (current != I)
{
return update_impl<I + 1>(dt, args...);
}
else
{
if (!current_started)
{
std::get<I>(children).start(args...);
current_started = true;
}
auto result = std::get<I>(children).update(dt, args...);
if (auto f = std::get_if<finished>(&result))
{
if (!(f->result))
{
current_started = false;
++current;
return update_impl<I + 1>(dt, args...);
}
else
return finished{true};
}
return result;
}
}
}
template <size_t I>
bool event_impl(Event const & e)
{
if constexpr (I == sizeof...(Children))
{
return false;
}
else
{
if (current == I)
{
return std::get<I>(children).event(e);
}
else
{
return event_impl<I + 1>(e);
}
}
}
};
};
}