Implement state machine infrastructure
This commit is contained in:
parent
325d49270d
commit
a0ad8e7ed6
|
@ -2,6 +2,7 @@
|
||||||
#define APPLICATION_H
|
#define APPLICATION_H
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <array>
|
||||||
#include <SFML/System/Clock.hpp>
|
#include <SFML/System/Clock.hpp>
|
||||||
#include <SFML/Window/Keyboard.hpp>
|
#include <SFML/Window/Keyboard.hpp>
|
||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
|
@ -12,18 +13,6 @@
|
||||||
class Application
|
class Application
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum State
|
|
||||||
{
|
|
||||||
SPLASH_SCREEN,
|
|
||||||
MAIN_MENU,
|
|
||||||
GAME_PICKER,
|
|
||||||
GAME,
|
|
||||||
EDITOR_PICKER,
|
|
||||||
EDITOR,
|
|
||||||
SETTINGS
|
|
||||||
};
|
|
||||||
|
|
||||||
Application();
|
Application();
|
||||||
void run();
|
void run();
|
||||||
void input();
|
void input();
|
||||||
|
@ -31,13 +20,14 @@ public:
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::stack<std::shared_ptr<GUIState>> _states;
|
std::array<std::shared_ptr<GUIState>, GUIState::Tag::AMOUNT> _states;
|
||||||
|
std::vector<std::shared_ptr<GUIState>> _state_stack;
|
||||||
|
|
||||||
sf::RenderWindow _game_window;
|
sf::RenderWindow _game_window;
|
||||||
std::shared_ptr<Game> _game;
|
std::shared_ptr<Game> _game;
|
||||||
|
|
||||||
State _state;
|
|
||||||
|
|
||||||
void exec();
|
void exec();
|
||||||
|
void emplaceState(GUIState::Tag new_state);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APPLICATION_H
|
#endif // APPLICATION_H
|
||||||
|
|
|
@ -3,14 +3,29 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
#include <SFML/Graphics/Drawable.hpp>
|
|
||||||
|
|
||||||
class GUIState : public sf::Drawable
|
class GUIState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum Tag {
|
||||||
|
SPLASH_SCREEN,
|
||||||
|
MAIN_MENU,
|
||||||
|
GAME_PICKER,
|
||||||
|
GAME,
|
||||||
|
EDITOR_PICKER,
|
||||||
|
EDITOR,
|
||||||
|
SETTINGS,
|
||||||
|
|
||||||
|
AMOUNT
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~GUIState() = default;
|
virtual ~GUIState() = default;
|
||||||
|
|
||||||
virtual void input(const sf::Event& event) = 0;
|
virtual void input(const sf::Event& event) = 0;
|
||||||
virtual void update() = 0;
|
virtual void update() = 0;
|
||||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const = 0;
|
virtual void draw() const = 0;
|
||||||
|
|
||||||
|
virtual void enter() = 0;
|
||||||
|
virtual void leave() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "classicgame/classicgraphicsmanager.h"
|
#include "classicgame/classicgraphicsmanager.h"
|
||||||
|
|
||||||
#include "gui/mainmenu.h"
|
#include "gui/mainmenu.h"
|
||||||
|
#include "gui/gamestate.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -19,13 +20,19 @@ Application::Application() :
|
||||||
_game_window.setMouseCursorGrabbed(false);
|
_game_window.setMouseCursorGrabbed(false);
|
||||||
_game_window.setVerticalSyncEnabled(true);
|
_game_window.setVerticalSyncEnabled(true);
|
||||||
|
|
||||||
_states.push(std::make_shared<MainMenu>(_game_window));
|
MainMenu::Callbacks callbacks = {[&](){ emplaceState(GUIState::Tag::GAME); }};
|
||||||
|
|
||||||
|
const auto main_menu = std::make_shared<MainMenu>(_game_window, std::move(callbacks));
|
||||||
|
const auto game_state = std::make_shared<GameState>(_game_window, _game, GameState::Callbacks());
|
||||||
|
_states[GUIState::Tag::MAIN_MENU] = main_menu;
|
||||||
|
_states[GUIState::Tag::GAME] = game_state;
|
||||||
|
|
||||||
|
_state_stack.emplace_back(_states.at(GUIState::Tag::MAIN_MENU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::run()
|
void Application::run()
|
||||||
{
|
{
|
||||||
_game_window.display();
|
_game_window.display();
|
||||||
|
|
||||||
exec();
|
exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,16 +68,8 @@ void Application::input()
|
||||||
_game_window.close();
|
_game_window.close();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sf::Event::KeyPressed:
|
|
||||||
case sf::Event::KeyReleased:
|
|
||||||
case sf::Event::MouseButtonReleased:
|
|
||||||
case sf::Event::MouseButtonPressed:
|
|
||||||
if (event.key.code == sf::Keyboard::Escape)
|
|
||||||
_game_window.close();
|
|
||||||
_states.top()->input(event);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
_state_stack.back()->input(event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,12 +77,22 @@ void Application::input()
|
||||||
|
|
||||||
void Application::update()
|
void Application::update()
|
||||||
{
|
{
|
||||||
_states.top()->update();
|
_state_stack.back()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::draw()
|
void Application::draw()
|
||||||
{
|
{
|
||||||
_game_window.clear();
|
_game_window.clear();
|
||||||
_game_window.draw(*_states.top());
|
|
||||||
|
for (const auto& state : _state_stack)
|
||||||
|
state->draw();
|
||||||
|
|
||||||
_game_window.display();
|
_game_window.display();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::emplaceState(GUIState::Tag new_state)
|
||||||
|
{
|
||||||
|
_state_stack.back()->leave();
|
||||||
|
_state_stack.emplace_back(_states.at(new_state));
|
||||||
|
_state_stack.back()->enter();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include "gamestate.h"
|
||||||
|
#include "widgets/button.h"
|
||||||
|
#include "widgets/group.h"
|
||||||
|
|
||||||
|
#include "game/game.h"
|
||||||
|
|
||||||
|
GameState::GameState(sf::RenderWindow& game_window, const std::shared_ptr<Game>& game,
|
||||||
|
Callbacks&& callbacks) :
|
||||||
|
_game(game),
|
||||||
|
_game_window(game_window),
|
||||||
|
_onLeaveGameCallback(callbacks.onLeaveGame)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void GameState::input(const sf::Event& event)
|
||||||
|
{
|
||||||
|
_game->input({0, event});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::update()
|
||||||
|
{
|
||||||
|
_game->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::draw() const
|
||||||
|
{
|
||||||
|
_game->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::enter()
|
||||||
|
{
|
||||||
|
_game->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GameState::leave()
|
||||||
|
{
|
||||||
|
_onLeaveGameCallback();
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gui/state.h"
|
||||||
|
#include <SFML/Graphics/RenderWindow.hpp>
|
||||||
|
|
||||||
|
class Group;
|
||||||
|
class Game;
|
||||||
|
|
||||||
|
class GameState : public GUIState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct Callbacks
|
||||||
|
{
|
||||||
|
std::function<void(void)> onLeaveGame;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
explicit GameState(sf::RenderWindow& game_window,
|
||||||
|
const std::shared_ptr<Game>& game,
|
||||||
|
Callbacks&& callbacks);
|
||||||
|
|
||||||
|
virtual void input(const sf::Event& event) override;
|
||||||
|
virtual void update() override;
|
||||||
|
virtual void draw() const override;
|
||||||
|
|
||||||
|
virtual void enter() override;
|
||||||
|
virtual void leave() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Game> _game;
|
||||||
|
sf::RenderWindow& _game_window;
|
||||||
|
|
||||||
|
std::function<void(void)> _onEnterGameCallback;
|
||||||
|
std::function<void(void)> _onLeaveGameCallback;
|
||||||
|
};
|
||||||
|
|
|
@ -2,16 +2,13 @@
|
||||||
#include "widgets/button.h"
|
#include "widgets/button.h"
|
||||||
#include "widgets/group.h"
|
#include "widgets/group.h"
|
||||||
|
|
||||||
MainMenu::MainMenu(sf::RenderWindow& game_window) :
|
MainMenu::MainMenu(sf::RenderWindow& game_window, Callbacks&& callbacks) :
|
||||||
_buttons(std::make_shared<Group>()),
|
_buttons(std::make_shared<Group>()),
|
||||||
_game_window(game_window)
|
_game_window(game_window)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Button> button_start = std::make_shared<Button>("Start");
|
std::shared_ptr<Button> button_start = std::make_shared<Button>("Start");
|
||||||
button_start->setRect(sf::FloatRect(140, 140, 500, 100));
|
button_start->setRect(sf::FloatRect(140, 140, 500, 100));
|
||||||
button_start->setCallback([&]()
|
button_start->setCallback(callbacks.onAppendGameState);
|
||||||
{
|
|
||||||
_game_window.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
std::shared_ptr<Button> button_exit = std::make_shared<Button>("Exit");
|
std::shared_ptr<Button> button_exit = std::make_shared<Button>("Exit");
|
||||||
button_exit->setRect(sf::FloatRect(140, 140, 400, 100));
|
button_exit->setRect(sf::FloatRect(140, 140, 400, 100));
|
||||||
|
@ -35,7 +32,18 @@ void MainMenu::update()
|
||||||
_buttons->update();
|
_buttons->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainMenu::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
void MainMenu::draw() const
|
||||||
{
|
{
|
||||||
target.draw(*_buttons, states);
|
_game_window.draw(*_buttons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainMenu::enter()
|
||||||
|
{
|
||||||
|
_buttons->setVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainMenu::leave()
|
||||||
|
{
|
||||||
|
_buttons->setVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,19 @@ class Group;
|
||||||
class MainMenu : public GUIState
|
class MainMenu : public GUIState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MainMenu(sf::RenderWindow& game_window);
|
|
||||||
|
struct Callbacks
|
||||||
|
{
|
||||||
|
std::function<void(void)> onAppendGameState;
|
||||||
|
};
|
||||||
|
|
||||||
|
MainMenu(sf::RenderWindow& game_window, Callbacks&& callbacks);
|
||||||
virtual void input(const sf::Event& event) override;
|
virtual void input(const sf::Event& event) override;
|
||||||
virtual void update() override;
|
virtual void update() override;
|
||||||
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
|
virtual void draw() const override;
|
||||||
|
|
||||||
|
virtual void enter() override;
|
||||||
|
virtual void leave() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Group> _buttons;
|
std::shared_ptr<Group> _buttons;
|
||||||
|
|
|
@ -14,10 +14,18 @@ void Widget::update()
|
||||||
|
|
||||||
void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||||
{
|
{
|
||||||
|
if (!_is_visible)
|
||||||
|
return;
|
||||||
|
|
||||||
for (auto& child : _children)
|
for (auto& child : _children)
|
||||||
child->draw(target, states);
|
child->draw(target, states);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::setVisibility(bool is_visible)
|
||||||
|
{
|
||||||
|
_is_visible = is_visible;
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::addChild(const std::shared_ptr<Widget> &child)
|
void Widget::addChild(const std::shared_ptr<Widget> &child)
|
||||||
{
|
{
|
||||||
child->_parent = shared_from_this();
|
child->_parent = shared_from_this();
|
||||||
|
|
|
@ -18,10 +18,12 @@ public:
|
||||||
virtual void setPosition(const sf::Vector2f& position) = 0;
|
virtual void setPosition(const sf::Vector2f& position) = 0;
|
||||||
virtual bool isUnderMouse(int mouse_x, int mouse_y) const = 0;
|
virtual bool isUnderMouse(int mouse_x, int mouse_y) const = 0;
|
||||||
|
|
||||||
|
void setVisibility(bool is_visible = true);
|
||||||
void addChild(const std::shared_ptr<Widget>& child);
|
void addChild(const std::shared_ptr<Widget>& child);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::shared_ptr<Widget>> _children;
|
std::vector<std::shared_ptr<Widget>> _children;
|
||||||
std::shared_ptr<Widget> _parent;
|
std::shared_ptr<Widget> _parent;
|
||||||
|
bool _is_visible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue