forked from NaiJi/project-kyoku
Implement state machine infrastructure
This commit is contained in:
parent
325d49270d
commit
a0ad8e7ed6
|
@ -2,6 +2,7 @@
|
|||
#define APPLICATION_H
|
||||
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <SFML/System/Clock.hpp>
|
||||
#include <SFML/Window/Keyboard.hpp>
|
||||
#include <SFML/Window/Event.hpp>
|
||||
|
@ -12,18 +13,6 @@
|
|||
class Application
|
||||
{
|
||||
public:
|
||||
|
||||
enum State
|
||||
{
|
||||
SPLASH_SCREEN,
|
||||
MAIN_MENU,
|
||||
GAME_PICKER,
|
||||
GAME,
|
||||
EDITOR_PICKER,
|
||||
EDITOR,
|
||||
SETTINGS
|
||||
};
|
||||
|
||||
Application();
|
||||
void run();
|
||||
void input();
|
||||
|
@ -31,13 +20,14 @@ public:
|
|||
void draw();
|
||||
|
||||
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;
|
||||
std::shared_ptr<Game> _game;
|
||||
|
||||
State _state;
|
||||
|
||||
void exec();
|
||||
void emplaceState(GUIState::Tag new_state);
|
||||
};
|
||||
|
||||
#endif // APPLICATION_H
|
||||
|
|
|
@ -3,14 +3,29 @@
|
|||
#include <stack>
|
||||
#include <memory>
|
||||
#include <SFML/Window/Event.hpp>
|
||||
#include <SFML/Graphics/Drawable.hpp>
|
||||
|
||||
class GUIState : public sf::Drawable
|
||||
class GUIState
|
||||
{
|
||||
public:
|
||||
|
||||
enum Tag {
|
||||
SPLASH_SCREEN,
|
||||
MAIN_MENU,
|
||||
GAME_PICKER,
|
||||
GAME,
|
||||
EDITOR_PICKER,
|
||||
EDITOR,
|
||||
SETTINGS,
|
||||
|
||||
AMOUNT
|
||||
};
|
||||
|
||||
virtual ~GUIState() = default;
|
||||
|
||||
virtual void input(const sf::Event& event) = 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 "gui/mainmenu.h"
|
||||
#include "gui/gamestate.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -19,13 +20,19 @@ Application::Application() :
|
|||
_game_window.setMouseCursorGrabbed(false);
|
||||
_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()
|
||||
{
|
||||
_game_window.display();
|
||||
|
||||
exec();
|
||||
}
|
||||
|
||||
|
@ -61,16 +68,8 @@ void Application::input()
|
|||
_game_window.close();
|
||||
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:
|
||||
_state_stack.back()->input(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -78,12 +77,22 @@ void Application::input()
|
|||
|
||||
void Application::update()
|
||||
{
|
||||
_states.top()->update();
|
||||
_state_stack.back()->update();
|
||||
}
|
||||
|
||||
void Application::draw()
|
||||
{
|
||||
_game_window.clear();
|
||||
_game_window.draw(*_states.top());
|
||||
|
||||
for (const auto& state : _state_stack)
|
||||
state->draw();
|
||||
|
||||
_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/group.h"
|
||||
|
||||
MainMenu::MainMenu(sf::RenderWindow& game_window) :
|
||||
MainMenu::MainMenu(sf::RenderWindow& game_window, Callbacks&& callbacks) :
|
||||
_buttons(std::make_shared<Group>()),
|
||||
_game_window(game_window)
|
||||
{
|
||||
std::shared_ptr<Button> button_start = std::make_shared<Button>("Start");
|
||||
button_start->setRect(sf::FloatRect(140, 140, 500, 100));
|
||||
button_start->setCallback([&]()
|
||||
{
|
||||
_game_window.close();
|
||||
});
|
||||
button_start->setCallback(callbacks.onAppendGameState);
|
||||
|
||||
std::shared_ptr<Button> button_exit = std::make_shared<Button>("Exit");
|
||||
button_exit->setRect(sf::FloatRect(140, 140, 400, 100));
|
||||
|
@ -35,7 +32,18 @@ void MainMenu::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
|
||||
{
|
||||
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 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:
|
||||
std::shared_ptr<Group> _buttons;
|
||||
|
|
|
@ -14,10 +14,18 @@ void Widget::update()
|
|||
|
||||
void Widget::draw(sf::RenderTarget& target, sf::RenderStates states) const
|
||||
{
|
||||
if (!_is_visible)
|
||||
return;
|
||||
|
||||
for (auto& child : _children)
|
||||
child->draw(target, states);
|
||||
}
|
||||
|
||||
void Widget::setVisibility(bool is_visible)
|
||||
{
|
||||
_is_visible = is_visible;
|
||||
}
|
||||
|
||||
void Widget::addChild(const std::shared_ptr<Widget> &child)
|
||||
{
|
||||
child->_parent = shared_from_this();
|
||||
|
|
|
@ -18,10 +18,12 @@ public:
|
|||
virtual void setPosition(const sf::Vector2f& position) = 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);
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<Widget>> _children;
|
||||
std::shared_ptr<Widget> _parent;
|
||||
bool _is_visible = true;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue