// // game_dispatch.cpp // gameutils // // Created by Sam Jaffe on 9/2/16. // #include #include "game/engine/game_dispatch.hpp" #include "game/engine/events.hpp" #include "game/engine/fps_counter.hpp" #include "game/engine/scene.hpp" #include "game/engine/text_engine.hpp" #include "game/graphics/object.hpp" #include "game/graphics/renderer.hpp" #include "game/util/env.hpp" #include "matrix/matrix_helpers.hpp" namespace engine { namespace { event::event_type mask(event::event_type t, bool pressed) { return static_cast( t | (pressed ? event::PRESSED_MASK : event::RELEASED_MASK)); } } game_dispatch::game_dispatch(std::shared_ptr renderer) : screen_size_(env::screen_size()), renderer_(renderer), batch_renderer_(make_renderer(screen_size_)), minimum_frame_duration_(0), text_engine_(new text_engine("font", renderer->manager())), counter_(new fps_counter(text_engine_)), scenes_(), current_timestamp(env::clock::now()), current_scene_() {} game_dispatch::~game_dispatch() {} void game_dispatch::register_scene(scene_t scn) { scenes_.emplace(scn->id, scn); } void game_dispatch::activate_scene(scene_id_t const & id) { // TODO: Cleanup current_scene_ = current_scene_info(scenes_[id]); } void game_dispatch::set_current_timestamp() { current_timestamp = env::clock::now(); } game_dispatch::current_scene_info::current_scene_info() {} game_dispatch::current_scene_info::current_scene_info(scene_t curr) : ptr(curr), current_scene_id(ptr->id), local_size(ptr->size()) {} graphics::manager const & game_dispatch::graphics_manager() const { return *renderer_->manager(); } void game_dispatch::process_key_event(raw_key_t key, bool press) { // if (!current_scene_.is_keyboard_event) return; auto const & binding = current_scene_.ptr->keys(); auto it = binding.find(key); if (it == binding.end()) return; current_scene_.ptr->handle_key_event( {it->second, mask(event::KEY_MASK, press)}); } void game_dispatch::process_mouse_event(math::vec2 mouse_pos, bool press) { // if (!current_scene_.is_mouse_event) return; math::vec2 local_scene_position = mouse_pos * current_scene_.local_size / screen_size_; current_scene_.ptr->handle_mouse_event( {local_scene_position, mask(event::MOUSE_MASK, press)}); } env::clock::tick game_dispatch::next_frame() { env::clock::tick t(current_timestamp); while (t.since < minimum_frame_duration_) { std::this_thread::sleep_for(minimum_frame_duration_ - t.since); t = env::clock::tick(current_timestamp); } current_timestamp = t.now; return t; } void game_dispatch::update() { env::clock::tick t = next_frame(); counter_->set_frame_step(t.since); current_scene_.ptr->update(std::chrono::duration(t.since).count()); } void game_dispatch::render() { batch_renderer_->clear(); counter_->render(*batch_renderer_); batch_renderer_->flush(); current_scene_.ptr->render(); renderer_->flush(); } std::shared_ptr game_dispatch::make_renderer(math::vec2 const & bounds) const { math::vec2 const factor = screen_size_ / bounds; float const scale = std::min(factor[0], factor[1]); return std::make_shared( renderer_.get(), math::matrix::scalar(make_vector(scale, scale, 1.f))); } }