Merge branch 'master' of github.com:tollyx/dungeon

This commit is contained in:
Adrian Hedqvist 2018-04-03 08:18:44 +02:00
commit 1505a13c99
28 changed files with 409 additions and 146 deletions

View file

@ -116,6 +116,7 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\Logger.cpp" />
<ClCompile Include="src\LuaHandler.cpp" />
<ClCompile Include="src\Shader.cpp" />
<ClCompile Include="src\Actor.cpp" />
@ -131,7 +132,6 @@
<ClCompile Include="src\ExploreNode.cpp" />
<ClCompile Include="src\FieldOfView.cpp" />
<ClCompile Include="src\FleeNode.cpp" />
<ClCompile Include="src\Gamestate.cpp" />
<ClCompile Include="src\Goblin.cpp" />
<ClCompile Include="src\HealFriendNode.cpp" />
<ClCompile Include="src\Hero.cpp" />
@ -139,11 +139,11 @@
<ClCompile Include="src\IfNotSeeEnemyNode.cpp" />
<ClCompile Include="src\IfSeeEnemyNode.cpp" />
<ClCompile Include="src\IfSeeFriendNode.cpp" />
<ClCompile Include="src\imgui.cpp" />
<ClCompile Include="src\imgui_demo.cpp" />
<ClCompile Include="src\imgui_draw.cpp" />
<ClCompile Include="src\imgui_impl_sdl_gl3.cpp" />
<ClCompile Include="src\imgui_user.cpp" />
<ClCompile Include="src\imgui\imgui.cpp" />
<ClCompile Include="src\imgui\imgui_demo.cpp" />
<ClCompile Include="src\imgui\imgui_draw.cpp" />
<ClCompile Include="src\imgui\imgui_impl_sdl_gl3.cpp" />
<ClCompile Include="src\imgui\imgui_user.cpp" />
<ClCompile Include="src\Input.cpp" />
<ClCompile Include="src\Main.cpp" />
<ClCompile Include="src\Mapgen.cpp" />
@ -156,9 +156,11 @@
<ClCompile Include="src\Shaman.cpp" />
<ClCompile Include="src\Tilemap.cpp" />
<ClCompile Include="src\SpriteAtlas.cpp" />
<ClCompile Include="src\Time.cpp" />
<ClCompile Include="src\WanderNode.cpp" />
<ClCompile Include="src\World.cpp" />
<ClCompile Include="src\TileSet.cpp" />
<ClCompile Include="src\statemachine\StateStack.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Item.h" />
@ -178,7 +180,6 @@
<ClInclude Include="src\ExploreNode.h" />
<ClInclude Include="src\FieldOfView.h" />
<ClInclude Include="src\FleeNode.h" />
<ClInclude Include="src\Gamestate.h" />
<ClInclude Include="src\gitparams.h" />
<ClInclude Include="src\Goblin.h" />
<ClInclude Include="src\HealFriendNode.h" />
@ -187,11 +188,11 @@
<ClInclude Include="src\IfNotSeeEnemyNode.h" />
<ClInclude Include="src\IfSeeEnemyNode.h" />
<ClInclude Include="src\IfSeeFriendNode.h" />
<ClInclude Include="src\imconfig.h" />
<ClInclude Include="src\imgui.h" />
<ClInclude Include="src\imgui_impl_sdl_gl3.h" />
<ClInclude Include="src\imgui_internal.h" />
<ClInclude Include="src\imgui_user.h" />
<ClInclude Include="src\imgui\imconfig.h" />
<ClInclude Include="src\imgui\imgui.h" />
<ClInclude Include="src\imgui\imgui_impl_sdl_gl3.h" />
<ClInclude Include="src\imgui\imgui_internal.h" />
<ClInclude Include="src\imgui\imgui_user.h" />
<ClInclude Include="src\Input.h" />
<ClInclude Include="src\Logger.h" />
<ClInclude Include="src\Mapgen.h" />
@ -203,16 +204,18 @@
<ClInclude Include="src\Rng.h" />
<ClInclude Include="src\Shaman.h" />
<ClInclude Include="src\Stats.h" />
<ClInclude Include="src\stb_rect_pack.h" />
<ClInclude Include="src\stb_textedit.h" />
<ClInclude Include="src\stb_truetype.h" />
<ClInclude Include="src\imgui\stb_rect_pack.h" />
<ClInclude Include="src\imgui\stb_textedit.h" />
<ClInclude Include="src\imgui\stb_truetype.h" />
<ClInclude Include="src\Tilemap.h" />
<ClInclude Include="src\SpriteAtlas.h" />
<ClInclude Include="src\Time.h" />
<ClInclude Include="src\vec2i.h" />
<ClInclude Include="src\WanderNode.h" />
<ClInclude Include="src\wglew.h" />
<ClInclude Include="src\World.h" />
<ClInclude Include="src\TileSet.h" />
<ClInclude Include="src\statemachine\StateStack.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -54,9 +54,6 @@
<ClCompile Include="src\FleeNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Gamestate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Goblin.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -78,21 +75,6 @@
<ClCompile Include="src\IfSeeFriendNode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui_demo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui_draw.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui_impl_sdl_gl3.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui_user.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Input.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -144,6 +126,30 @@
<ClCompile Include="src\LuaHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\statemachine\StateStack.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui\imgui.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui\imgui_demo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui\imgui_draw.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui\imgui_impl_sdl_gl3.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\imgui\imgui_user.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\Time.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Actor.h">
@ -188,9 +194,6 @@
<ClInclude Include="src\FleeNode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Gamestate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\gitparams.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -215,21 +218,6 @@
<ClInclude Include="src\IfSeeFriendNode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imconfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui_impl_sdl_gl3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui_internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui_user.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Input.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -260,15 +248,6 @@
<ClInclude Include="src\Stats.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\stb_rect_pack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\stb_textedit.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\stb_truetype.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Tilemap.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -302,5 +281,35 @@
<ClInclude Include="src\LuaHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\statemachine\StateStack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\imconfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\imgui.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\imgui_impl_sdl_gl3.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\imgui_internal.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\imgui_user.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\stb_rect_pack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\stb_textedit.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\imgui\stb_truetype.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\Time.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View file

@ -9,11 +9,12 @@
#include <string>
#include <kaguya/kaguya.hpp>
#include "Renderer.h"
#include "imgui.h"
#include "imgui/imgui.h"
#include "Input.h"
#include "Gamestate.h"
#include "PlayState.h"
#include "LuaHandler.h"
#include "Time.h"
#include <memory>
Uint64 perfFreq;
double currTime() {
@ -108,12 +109,8 @@ int App::start() {
double accumulator = dt;
bool show_log = false;
bool running = true;
Gamestate* nextstate = nullptr;
current = new PlayState();
current->init(this);
current->load();
running = true;
statestack.push(std::unique_ptr<IState>(new PlayState(this)));
while (running) {
double newTime = currTime();
@ -122,19 +119,12 @@ int App::start() {
frametime = 1.0/30;
}
if (nextstate != nullptr) {
current->quit();
delete current;
current = nextstate;
current->init(this);
current->load();
}
currentTime = newTime;
accumulator += frametime;
SDL_Event ev{};
ImGuiIO &io = ImGui::GetIO();
renderer->ImguiNewFrame();
while (SDL_PollEvent(&ev)) {
//renderer->ImguiProcessEvents(&ev);
@ -154,31 +144,31 @@ int App::start() {
case SDL_MOUSEMOTION:
if (!io.WantCaptureMouse) {
InputEvent inputEvent = input->set_mouse_pos(ev.motion.x, ev.motion.y, ev.motion.xrel, ev.motion.yrel);
current->inputevent(&inputEvent);
statestack.input(inputEvent);
}
break;
case SDL_MOUSEBUTTONDOWN:
if (!io.WantCaptureMouse) {
InputEvent inputEvent = input->set_mouse_button(ev.button.button, ev.button.x, ev.button.y, true);
current->inputevent(&inputEvent);
statestack.input(inputEvent);
}
break;
case SDL_MOUSEBUTTONUP:
if (!io.WantCaptureMouse) {
InputEvent inputEvent = input->set_mouse_button(ev.button.button, ev.button.x, ev.button.y, false);
current->inputevent(&inputEvent);
statestack.input(inputEvent);
}
break;
case SDL_KEYDOWN:
if (!io.WantCaptureKeyboard) {
InputEvent inputEvent = input->set_key(ev.key.keysym.sym, (SDL_Keymod) ev.key.keysym.mod, true);
current->inputevent(&inputEvent);
statestack.input(inputEvent);
}
break;
case SDL_KEYUP:
if (!io.WantCaptureKeyboard){
InputEvent inputEvent = input->set_key(ev.key.keysym.sym, (SDL_Keymod) ev.key.keysym.mod, false);
current->inputevent(&inputEvent);
statestack.input(inputEvent);
}
break;
case SDL_QUIT:
@ -189,13 +179,13 @@ int App::start() {
}
}
while (running && accumulator >= dt) {
nextstate = current->update(dt);
statestack.update(dt);
input->new_frame();
Time::tick_timers(dt);
accumulator -= dt;
}
renderer->Clear();
current->draw(accumulator / dt);
statestack.draw();
renderer->Present();
SDL_Delay(1);
}

View file

@ -5,7 +5,8 @@
#ifndef DUNGEON_APP_H
#define DUNGEON_APP_H
class Gamestate;
#include "statemachine/StateStack.h"
class Renderer;
class Input;
@ -14,9 +15,10 @@ class Input;
#define ADD_QUOTES(s) ADD_QUOTES_HELPER(s)
class App {
bool running = true;
public:
const char* version = ADD_QUOTES(GIT_CUR_COMMIT);
Gamestate* current;
StateStack statestack;
Renderer* renderer;
Input* input;
bool init();

View file

@ -1,10 +0,0 @@
//
// Created by Adrian on 2017-09-19.
//
#include "Gamestate.h"
#include "App.h"
void Gamestate::init(App *app) {
this->app = app;
}

View file

@ -1,25 +0,0 @@
//
// Created by Adrian on 2017-09-19.
//
#ifndef DUNGEON_GAMESTATE_H
#define DUNGEON_GAMESTATE_H
class App;
struct InputEvent;
class Gamestate {
protected:
App* app;
public:
virtual ~Gamestate() = default;
void init(App* app);
virtual void load() = 0;
virtual Gamestate* update(double delta) = 0;
virtual void draw(double delta) = 0;
virtual void quit() = 0;
virtual void inputevent(InputEvent* event) = 0;
};
#endif //DUNGEON_GAMESTATE_H

39
src/Logger.cpp Normal file
View file

@ -0,0 +1,39 @@
#include "Logger.h"
#include <SDL2/SDL.h>
#include <io.h>
Log::LogLevel log_level = Log::LogLevel::Warning;
void Log::set_log_level(LogLevel level) {
log_level = level;
}
void Log::error(string tag, string message) {
if (log_level <= LogLevel::Error) {
printf("[ERR] <%s> %s\n", tag, message);
}
}
void Log::warning(string tag, string message) {
if (log_level <= LogLevel::Warning) {
printf("[WRN] <%s> %s\n", tag, message);
}
}
void Log::info(string tag, string message) {
if (log_level <= LogLevel::Info) {
printf("[INF] <%s> %s\n", tag, message);
}
}
void Log::debug(string tag, string message) {
if (log_level <= LogLevel::Debug) {
printf("[DBG] <%s> %s\n", tag, message);
}
}
void Log::trace(string tag, string message) {
if (log_level <= LogLevel::Trace) {
printf("[TRC] <%s> %s\n", tag, message);
}
}

View file

@ -1,5 +1,23 @@
#pragma once
#include <string>
namespace Logger {
namespace Log {
using std::string;
}
enum LogLevel {
Error,
Warning,
Info,
Debug,
Trace,
};
void set_log_level(LogLevel level);
//void enable_log_to_file(bool enable);
//void set_log_path(string path);
void error(string tag, string message);
void warning(string tag, string message);
void info(string tag, string message);
void debug(string tag, string message);
void trace(string tag, string message);
}

View file

@ -10,7 +10,7 @@
#include "SpriteAtlas.h"
#include "Mapgen.h"
#include "FieldOfView.h"
#include "imgui.h"
#include "imgui/imgui.h"
#include "Hero.h"
#include "Goblin.h"
#include "Shaman.h"
@ -23,13 +23,14 @@ InputAction player_action;
TileSet tileset;
LuaHandler handler;
void PlayState::load() {
void PlayState::enter() {
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating ascii tileset...\n");
ascii = new SpriteAtlas(app->renderer, "./assets/12x12.bmp", 192, 192, 12, 12);
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Created ascii tileset.\n");
handler.load_module("data", &tileset);
// TODO: Load all this from Lua
app->input->bind_key(SDLK_ESCAPE, ACTION_ESCAPE_MENU);
// Movement: keypad
@ -71,6 +72,10 @@ void PlayState::load() {
new_game();
}
PlayState::PlayState(App * app) {
this->app = app;
}
void PlayState::new_game() {
player_action = ACTION_NONE;
@ -104,7 +109,7 @@ void PlayState::new_game() {
}
}
Gamestate *PlayState::update(double delta) {
StateResult PlayState::update(float delta) {
while (!is_player_turn || player_action != ACTION_NONE) {
std::vector<Actor*>* actors = tilemap->get_actor_list();
Actor* actor = actors->at(current_entity_index);
@ -128,14 +133,17 @@ Gamestate *PlayState::update(double delta) {
if (tilemap->get_tile(pos.x, pos.y).has_tag("exit")) {
current_level++;
tilemap = &world.GetMap(current_level, tileset);
return nullptr;
return StateResult::None();
}
else {
return nullptr;
return StateResult::None();
}
break;
}
default: player_action = ACTION_NONE; SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Turn aborted: no player action.\n"); return nullptr; // abort turn
default:
player_action = ACTION_NONE;
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Turn aborted: no player action.\n");
return StateResult::None(); // abort turn
}
if (dir != vec2i(0,0)) {
if (!actor->move(dir.x, dir.y, tilemap)) {
@ -152,7 +160,7 @@ Gamestate *PlayState::update(double delta) {
if(!attacked) {
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Turn aborted: invalid player action.\n");
player_action = ACTION_NONE;
return nullptr; // unable to move and nothing to attack == abort turn
return StateResult::None(); // unable to move and nothing to attack == abort turn
}
}
}
@ -173,10 +181,10 @@ Gamestate *PlayState::update(double delta) {
fov.calc(player_actor->get_position(), 6);
}
}
return nullptr;
return StateResult::None();
}
void PlayState::draw(double delta) {
void PlayState::draw() {
if (debug) {
{
ImGui::BeginMainMenuBar();
@ -286,17 +294,17 @@ void PlayState::draw(double delta) {
}
}
void PlayState::quit() {
void PlayState::exit() {
}
void PlayState::inputevent(InputEvent *event) {
if (event->type == INPUT_KEY_EVENT && event->pressed) {
switch (event->action) {
void PlayState::input(InputEvent &event) {
if (event.type == INPUT_KEY_EVENT && event.pressed) {
switch (event.action) {
case ACTION_TOGGLE_DEBUG: debug = !debug; break;
case ACTION_RESET: new_game(); break;
case ACTION_ESCAPE_MENU: break; // TODO
case ACTION_NONE: break;
default: player_action = event->action; break;
default: player_action = event.action; break;
}
}
}

View file

@ -1,14 +1,15 @@
#pragma once
#include "Gamestate.h"
#include "statemachine/StateStack.h"
#include "Tilemap.h"
#include "FieldOfView.h"
#include "World.h"
class SpriteAtlas;
class Actor;
class App;
class PlayState : public Gamestate {
class PlayState : public IState {
SpriteAtlas* ascii;
World world;
Tilemap* tilemap;
@ -25,11 +26,14 @@ class PlayState : public Gamestate {
bool debug_settings = false;
bool debug_disable_fov = false;
App* app;
public:
PlayState(App* app);
void new_game();
void load() override;
Gamestate* update(double delta) override;
void draw(double delta) override;
void quit() override;
void inputevent(InputEvent* event) override;
void enter() override;
StateResult update(float delta) override;
void draw() override;
void exit() override;
void input(InputEvent& event) override;
};

View file

@ -6,8 +6,8 @@
#include <fstream>
#include <SDL2/SDL.h>
#include "imgui.h"
#include "imgui_impl_sdl_gl3.h"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_sdl_gl3.h"
#include <glm/gtx/transform.hpp>
#include <glm/matrix.hpp>
#include <utility>

67
src/Time.cpp Normal file
View file

@ -0,0 +1,67 @@
#include "Time.h"
#include <vector>
std::vector<Time::Timer> timers;
void Time::Timer::tick(float dt) {
time_current += dt;
if (continuous) {
callback();
}
else if (time_current >= duration) {
callback();
if (loop && !is_finished()) {
count++;
time_current -= duration;
}
}
}
bool Time::Timer::is_finished() {
return (loop && count >= limit) || (!loop && time_current >= duration);
}
void Time::tick_timers(float dt) {
for (int i = timers.size() - 1; i >= 0; i--) {
timers[i].tick(dt);
if (timers[i].is_finished()) {
timers.erase(timers.begin() + i);
}
}
}
void Time::after(float seconds, TimerCallback callback) {
timers.emplace_back(Timer {
false,
false,
0,
0,
0,
seconds,
callback,
});
}
void Time::every(float seconds, int limit, TimerCallback callback) {
timers.emplace_back(Timer{
true,
false,
limit,
0,
0,
seconds,
callback,
});
}
void Time::during(float seconds, TimerCallback callback) {
timers.emplace_back(Timer{
false,
true,
0,
0,
0,
seconds,
callback,
});
}

23
src/Time.h Normal file
View file

@ -0,0 +1,23 @@
#pragma once
#include <functional>
namespace Time {
typedef std::function<void()> TimerCallback;
struct Timer {
bool loop;
bool continuous;
int limit;
int count;
float time_current;
float duration;
TimerCallback callback;
void tick(float dt);
bool is_finished();
};
void tick_timers(float dt);
void after(float seconds, TimerCallback callback);
void every(float seconds, int limit, TimerCallback callback);
void during(float seconds, TimerCallback callback);
}

View file

@ -0,0 +1,69 @@
#include "StateStack.h"
void StateStack::update(float dt) {
update_state(stack.size() - 1, dt);
}
void StateStack::draw() {
draw_state(stack.size() - 1);
}
void StateStack::push(std::unique_ptr<IState> state) {
state->enter();
stack.emplace_back(std::move(state));
}
void StateStack::swap(std::unique_ptr<IState> state) {
pop();
push(std::move(state));
}
void StateStack::pop() {
stack.back()->exit();
stack.pop_back();
}
void StateStack::input(InputEvent & input_event) {
input_state(stack.size() - 1, input_event);
}
void StateStack::draw_state(unsigned int i) {
IState &state = *stack[i];
if (state.should_draw_previous() && i > 0) {
draw_state(i - 1);
}
state.draw();
}
void StateStack::update_state(unsigned int i, float dt) {
IState &state = *stack[i];
if (state.should_update_previous() && i > 0) {
update_state(i - 1, dt);
}
StateResult r = state.update(dt);
if (r.action != StateAction::None && i+1 != stack.size()) {
while (i < stack.size()) {
pop();
}
}
switch (r.action) {
case StateAction::Pop:
pop();
case StateAction::Push:
push(std::move(r.state.value()));
case StateAction::Swap:
swap(std::move(r.state.value()));
default:
break;
}
}
void StateStack::input_state(unsigned int i, InputEvent & input_event) {
IState &state = *stack[i];
if (state.should_update_previous() && i > 0) {
input_state(i - 1, input_event);
}
state.input(input_event);
}

View file

@ -0,0 +1,66 @@
#pragma once
#include <memory>
#include <optional>
#include <vector>
#include "../Input.h"
class StateStack;
class IState;
enum class StateAction {
None,
Push,
Pop,
Swap,
};
struct StateResult {
StateResult(StateAction action, std::optional<std::unique_ptr<IState>> state) {
this->action = action;
this->state.swap(state);
}
StateAction action;
std::optional<std::unique_ptr<IState>> state;
static StateResult None() {
return StateResult(StateAction::None, nullptr);
}
static StateResult Pop() {
return StateResult(StateAction::Pop, nullptr);
}
};
class IState {
public:
IState() = default;
virtual ~IState() = default;
virtual void enter() = 0;
virtual void exit() = 0;
virtual StateResult update(float dt) = 0;
virtual bool should_update_previous() { return false; };
virtual void draw() = 0;
virtual bool should_draw_previous() { return false; };
virtual void input(InputEvent &const event) = 0;
virtual bool should_input_previous() { return false; };
};
class StateStack {
public:
StateStack() = default;
~StateStack() = default;
void update(float dt);
void draw();
void push(std::unique_ptr<IState> state);
void swap(std::unique_ptr<IState> state);
void pop();
void input(InputEvent& input_event);
private:
void draw_state(unsigned int i);
void update_state(unsigned int i, float dt);
void input_state(unsigned int i, InputEvent &input_event);
std::vector<std::unique_ptr<IState>> stack;
};