Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SFML Game Development.pdf
Скачиваний:
209
Добавлен:
28.03.2016
Размер:
4.19 Mб
Скачать

Diverting the Game Flow – State Stack

A member function StateStack::registerState() inserts such mappings. The template parameter T is the derived state class we want to register. A lambda expression acts as a factory for the state: It creates an object of the derived class T by passing the stack and context to its constructor. This object is wrapped into a unique pointer and returned as a base class pointer. The lambda expression is assigned to the corresponding state ID in the map:

template <typename T>

void StateStack::registerState(States::ID stateID)

{

mFactories[stateID] = [this] ()

{

return State::Ptr(new T(*this, mContext));

};

}

This approach has the advantage that the StateStack class need not know the concrete state classes, we thus keep dependencies low. For state classes that take more than two parameters, we can write an overload to pass an additional argument (which will be done in later chapters). If your compiler supports variadic templates, a single function template will handle all these cases.

The createState() method takes an ID of a state, and returns a smart pointer to a newly created object of the corresponding state class. It does so by looking up the ID in the map and invoking the stored std::function factory, which returns the std::unique_ptr to the State base class:

State::Ptr StateStack::createState(States::ID stateID)

{

auto found = mFactories.find(stateID); assert(found != mFactories.end());

return found->second();

}

Handling updates, input, and drawing

Until this point, we taught the concept of the stack and the states it holds. Now it is time to feed our StateStack and consequently our active State objects with events, update, and drawing orders.

[ 118 ]

www.it-ebooks.info

Chapter 5

Input

Every polled event is fed to the state stack. Then, internally, the stack will deliver that event to the active states:

void StateStack::handleEvent(const sf::Event& event)

{

for (auto itr = mStack.rbegin(); itr != mStack.rend(); ++itr)

{

if (!(*itr)->handleEvent(event)) return;

}

applyPendingChanges();

}

In this for loop, you can verify that we iterate the active stack from the end to the beginning, in other words, from the highest state to the lowest. And, if any of the states returns false in its handleEvent() method, the loop is immediately ended.

This gives the control to the states that may not want to let input flow to other states than itself!

Update

The updating happens under the same guidelines of event handling, both the delivery order and the stopping of update propagation to lower states, if desired.

Draw

Drawing is straightforward; the StateStack class will order every active state to render itself.

The first state to be drawn is the lowest and oldest on the stack, and only then come the others, in order. This grants that the states are transparent, and you will be able to see the underlying screens. Anyway, if you don't desire to see pixels from the lower states, you can use sf::RectangleShape to draw a colored rectangle over the whole screen, blocking the undesired graphics, as you will see later in this chapter.

[ 119 ]

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]