diff options
Diffstat (limited to 'src/control/RPGEdit.cpp')
-rw-r--r-- | src/control/RPGEdit.cpp | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/src/control/RPGEdit.cpp b/src/control/RPGEdit.cpp index 679796c..0c55a6b 100644 --- a/src/control/RPGEdit.cpp +++ b/src/control/RPGEdit.cpp @@ -28,62 +28,99 @@ #include "MapContext.hpp" #include "../view/MapView.hpp" -#include <SDL.h> +namespace RPGEdit { -#define MIN_FRAME_DELAY 10 +namespace Control { +bool RPGEdit::handleSystemEvent(const SDL_Event &event) { + uint64_t time = timeProvider.now(); -namespace RPGEdit { + switch (event.type) { + case SDL_KEYDOWN: + eventBus.enqueue([=] { inputHandler.keyPressed(event.key.keysym.scancode, time); }, time); + break; -namespace Control { + case SDL_KEYUP: + eventBus.enqueue([=] { inputHandler.keyReleased(event.key.keysym.scancode, time); }, time); + break; -bool RPGEdit::systemIter(unsigned ticks) { - int timeout = 0; + case SDL_QUIT: + return false; + } - SDL_Event event; - if (SDL_WaitEventTimeout(&event, timeout)) { - switch (event.type) { - case SDL_KEYDOWN: - inputHandler.keyPressed(event.key.keysym.scancode); - break; + return true; +} - case SDL_KEYUP: - inputHandler.keyReleased(event.key.keysym.scancode); - break; +void RPGEdit::systemLoop() { + const int MIN_FRAME_DELAY = 10; + + uint32_t lastFrameTicks = SDL_GetTicks(); + + while (true) { + uint32_t diff = SDL_GetTicks() - lastFrameTicks; + int timeout = std::max(MIN_FRAME_DELAY - int(diff), 0); - case SDL_QUIT: - return false; + SDL_Event event; + if (SDL_WaitEventTimeout(&event, timeout)) { + if (!handleSystemEvent(event)) + return; + + continue; } - } - ctx->advance(&inputHandler, ticks); + lastFrameTicks = SDL_GetTicks(); - Model::Position pos = ctx->getViewPosition(); - mapView->render(pos.x, pos.y); + { + std::unique_lock<std::mutex> lock(modelMutex); - return true; + uint64_t time = timeProvider.now(); + + while (time >= handledTime) { + modelCond.wait(lock); + time = timeProvider.now(); + } + + Model::Position pos = ctx->getViewPosition(time); + mapView->render(pos.x, pos.y, time); + } + + SDL_RenderPresent(window->getRenderer()); + } } -void RPGEdit::systemLoop() { - uint32_t ticks1 = SDL_GetTicks(); - uint32_t ticks2 = ticks1; +void RPGEdit::eventLoop() { + while (true) { + EventBus::EventEntry event = eventBus.get(&timeProvider); - while (systemIter(ticks2 - ticks1)) { - ticks1 = ticks2; - ticks2 = SDL_GetTicks(); + if (!event.second) + return; + + { + std::lock_guard<std::mutex> lock(modelMutex); + + event.second(); + + handledTime = eventBus.peek(); + modelCond.notify_one(); + } } } void RPGEdit::run() { std::shared_ptr<Model::Map> map = Model::Map::load("test"); - ctx = std::make_shared<MapContext>(&tileLoader, map); + ctx = std::make_shared<MapContext>(&eventBus, &inputHandler, &tileLoader, map); window = std::make_shared<View::Window>(); mapView = ctx->initView(window); + eventThread = std::thread([this] { eventLoop(); }); + systemLoop(); + + eventBus.enqueue(EventBus::Event(), timeProvider.now()); + eventThread.join(); } } |