Reputation: 541
I'm writing my own little game-engine. To separate the option-menu from the main-menu and from the main-game and so on I thought of making a state-system, where everything mentioned above is an own state. The engines main-loop calls a tick() method on the current State. But now the engine knows nothing about interaction between the states, when to switch states and so on. To address this problem I implemented the following: the tick()-method of the states returns a template type: commandset. The Engine gets an Eventhandler to handle the return value of the tick() - methods. It looks like this:
template<class StateHandler, typename FeedbackType>
void Engine<StateHandler, FeedbackType>::run()
{
run = true;
clock.restart();
while (run)
{
sf::Time elapsed = clock.restart();
Win->clear(sf::Color::Black);
processEvents();
if (!pause)
{
Handler(currentState->tick(elapsed), *this);
if (overlayState != NULL)
Handler(overlayState->tick(elapsed), *this);
}
Win->display();
}
}
So, the engine calls the handler on the return value of tick, and passes itself to it. So that the Handler can interact with the engine. (The Variable Handler is of the type StateHandler)
And now when I wanted to test everything, and wrote a Teststate, and a handler, I ran into trouble. For later uses I intended to use a class as handler, but for the simple test purpose I wanted to use a function. So when I wanted to write the function, I noticed, that I can't define the second parameter, the engine, because its template argument would be the type of the function(which depends on the Engines type, which depends on the functions type ...).
And now my question: How can I define the Handler? Or is the whole idea garbage? (which would be really tragic, because I kinda like it)
Upvotes: 1
Views: 92
Reputation: 72062
Is a function so much less work that it's worth worrying over?
struct TestHandler {
void operator ()(const CommandSet& cs, Engine<TestHandler, TestFeedback>& e) {
}
};
If you really want a function, you have to jump through hoops. For perverse pleasure, I've added a way to make this work:
class any_ref {
public:
template <typename T>
any_ref(T& ref)
: pointer(&ref)
#if !defined(NDEBUG)
, type(&typeid(T))
#endif
{}
template <typename T>
T& get() const {
assert(typeid(T) == *type);
return *static_cast<T*>(pointer);
}
private:
void* pointer;
#if !defined(NDEBUG)
const std::type_info* type;
#endif
};
void TestHandler(const CommandSet& cs, any_ref er) {
auto& e = er.get<Engine<void (*)(const CommandSet&, any_ref), TestFeedback>>();
}
Upvotes: 2