diff --git a/include/Core/EventBroker.h b/include/Core/EventBroker.h index cb5e39c..ce2a5a4 100644 --- a/include/Core/EventBroker.h +++ b/include/Core/EventBroker.h @@ -24,6 +24,7 @@ #include #include #include +#include #define EVENT_SUBSCRIBE_MEMBER(relay, handler) \ relay = decltype(relay)(std::bind(handler, this, std::placeholders::_1)); \ @@ -123,16 +124,23 @@ public: void Unsubscribe(BaseEventRelay &relay); private: + bool m_IsProcessing = false; + typedef std::string ContextTypeName_t; // typeid(ContextType).name() typedef std::string EventTypeName_t; // typeid(EventType).name() typedef std::unordered_multimap EventRelays_t; typedef std::unordered_map ContextRelays_t; ContextRelays_t m_ContextRelays; + std::vector m_RelaysToSubscribe; + std::vector m_RelaysToUnsubscribe; typedef std::list>> EventQueue_t; std::shared_ptr m_EventQueueRead; std::shared_ptr m_EventQueueWrite; + + void subscribeImmediate(BaseEventRelay& relay); + void unsubscribeImmediate(BaseEventRelay& relay); }; template diff --git a/include/GUI/NumberFrame.h b/include/GUI/NumberFrame.h index ac51aed..7241b82 100644 --- a/include/GUI/NumberFrame.h +++ b/include/GUI/NumberFrame.h @@ -1,6 +1,8 @@ #ifndef GUI_NUMBERFRAME_H__ #define GUI_NUMBERFRAME_H__ +#include + #include "GUI/TextureFrame.h" namespace dd @@ -14,32 +16,16 @@ public: NumberFrame(Frame* parent, std::string name) : Frame(parent, name) { - m_NumberTextures[0] = "Textures/GUI/Numbers/N0.png"; - m_NumberTextures[1] = "Textures/GUI/Numbers/N1.png"; - m_NumberTextures[2] = "Textures/GUI/Numbers/N2.png"; - m_NumberTextures[3] = "Textures/GUI/Numbers/N3.png"; - m_NumberTextures[4] = "Textures/GUI/Numbers/N4.png"; - m_NumberTextures[5] = "Textures/GUI/Numbers/N5.png"; - m_NumberTextures[6] = "Textures/GUI/Numbers/N6.png"; - m_NumberTextures[7] = "Textures/GUI/Numbers/N7.png"; - m_NumberTextures[8] = "Textures/GUI/Numbers/N8.png"; - m_NumberTextures[9] = "Textures/GUI/Numbers/N9.png"; - - // Create number frame if missing - for (int i = 0; i < 10; i++) { - auto frame = new GUI::TextureFrame(this, "NumberFrameDigit"); - frame->SetTexture(m_NumberTextures[0]); - frame->DisableScissor(); - // Position frame based on alignment - if (i > 0) { - frame->X = i * 20; - } - Width += frame->Width; - if (Height < frame->Height) { - Height = frame->Height; - } - m_NumberFrames.push_front(frame); - } + m_CharacterTextures['0'] = "Textures/GUI/Numbers/N0.png"; + m_CharacterTextures['1'] = "Textures/GUI/Numbers/N1.png"; + m_CharacterTextures['2'] = "Textures/GUI/Numbers/N2.png"; + m_CharacterTextures['3'] = "Textures/GUI/Numbers/N3.png"; + m_CharacterTextures['4'] = "Textures/GUI/Numbers/N4.png"; + m_CharacterTextures['5'] = "Textures/GUI/Numbers/N5.png"; + m_CharacterTextures['6'] = "Textures/GUI/Numbers/N6.png"; + m_CharacterTextures['7'] = "Textures/GUI/Numbers/N7.png"; + m_CharacterTextures['8'] = "Textures/GUI/Numbers/N8.png"; + m_CharacterTextures['9'] = "Textures/GUI/Numbers/N9.png"; SetNumber(0); } @@ -50,41 +36,40 @@ public: m_Number = number; // Clear number textures - //for (auto& frame : m_NumberFrames) { - // frame->SetTexture(""); - //} + for (auto& frame : m_NumberFrames) { + frame->SetTexture(""); + } - //Width = 0; - //Height = 0; + Width = 0; + Height = 0; - int n = 0; - do { -// // Create number frame if missing -// if (m_NumberFrames.size() <= n) { -// auto frame = new GUI::TextureFrame(this, "NumberFrameDigit"); -// frame->DisableScissor(); -// m_NumberFrames.push_front(frame); -// } + std::string digits = std::to_string(number); + + int i = 0; + for (char& c : digits) { + // Create number frame if missing + if (i >= m_NumberFrames.size()) { + auto frame = new GUI::TextureFrame(this, "NumberFrameDigit"); + if (i > 0) { + frame->SetLeft(m_NumberFrames[i - 1]->Right()); + } + frame->DisableScissor(); + m_NumberFrames.push_back(frame); + } // Update value - int digit = number % 10; - m_NumberFrames[n]->SetTexture(m_NumberTextures[digit]); - //Width += m_NumberFrames[n]->Width; - //if (Height < m_NumberFrames[n]->Height) { - // Height = m_NumberFrames[n]->Height; - //} -// // Position frame based on alignment -// if (n > 0) { -// if (!m_LeftAligned) { -// m_NumberFrames[n]->SetLeft(m_NumberFrames[n - 1]->Right()); -// } else { -// m_NumberFrames[n]->SetRight(m_NumberFrames[n - 1]->Left()); -// } -// } + std::string texture = "Textures/Core/ErrorTexture.png"; + if (m_CharacterTextures.find(c) != m_CharacterTextures.end()) { + texture = m_CharacterTextures.at(c); + } + m_NumberFrames[i]->SetTexture(m_CharacterTextures.at(c)); + Width += m_NumberFrames[i]->Width; + if (Height < m_NumberFrames[i]->Height) { + Height = m_NumberFrames[i]->Height; + } - number /= 10; - n++; - } while (number > 0); + i++; + } } void SetLeftAlign() { m_LeftAligned = true; } @@ -99,7 +84,7 @@ private: int m_Number = 0; bool m_LeftAligned = true; - std::string m_NumberTextures[10]; + std::unordered_map m_CharacterTextures; std::deque m_NumberFrames; }; diff --git a/include/Game/FPSCounter.h b/include/Game/FPSCounter.h new file mode 100644 index 0000000..0f7f303 --- /dev/null +++ b/include/Game/FPSCounter.h @@ -0,0 +1,43 @@ +#ifndef GUI_FPSCOUNTER_H__ +#define GUI_FPSCOUNTER_H__ + +#include "GUI/Frame.h" +#include "GUI/NumberFrame.h" + +namespace dd +{ +namespace GUI +{ + +class FPSCounter : public Frame +{ +public: + FPSCounter(Frame* parent, std::string name) + : Frame(parent, name) + { + m_FrameTimes.resize(m_MaxSamples); + m_Numbers = new GUI::NumberFrame(this, "FPSCounterNumberFrame"); + } + + virtual void Update(double dt) + { + m_FrameTimes[m_CurrentFrame % m_MaxSamples] = dt; + double sum = std::accumulate(m_FrameTimes.begin(), m_FrameTimes.end(), 0.0); + sum /= std::min(m_CurrentFrame, m_MaxSamples); + m_Numbers->SetNumber(std::round(1.0 / sum)); + + m_CurrentFrame++; + } + +private: + NumberFrame* m_Numbers = nullptr; + + int m_MaxSamples = 100; + int m_CurrentFrame = 0; + std::vector m_FrameTimes; +}; + +} +} +#endif + diff --git a/include/Game/HUD.h b/include/Game/HUD.h index 2a240b3..52711e8 100644 --- a/include/Game/HUD.h +++ b/include/Game/HUD.h @@ -6,6 +6,7 @@ #include "GUI/NumberFrame.h" #include "Core/EKeyUp.h" #include "Game/EScoreEvent.h" +#include "Game/FPSCounter.h" namespace dd { @@ -24,6 +25,15 @@ public: m_LevelIndicator = new GUI::TextureFrame(this, "HUDLevelIndicator"); m_LevelIndicator->SetTexture("Textures/GUI/HUD/LevelIndicatorBG.png"); + m_AreaNumberFrame = new GUI::NumberFrame(m_LevelIndicator, "HUDScoreNumberFrameawdawdwa"); + m_AreaNumberFrame->X = 132; + m_AreaNumberFrame->Y = 19; + m_AreaNumberFrame->SetNumber(6); + m_StageNumberFrame = new GUI::NumberFrame(m_LevelIndicator, "HUDScoreNumberFrameawdawdwa"); + m_StageNumberFrame->X = 165; + m_StageNumberFrame->Y = 19; + m_StageNumberFrame->SetNumber(5); + m_ScoreIndicator = new GUI::TextureFrame(this, "HUDScoreIndicator"); m_ScoreIndicator->SetTexture("Textures/GUI/HUD/ScoreIndicatorBG.png"); m_ScoreIndicator->SetRight(Right()); @@ -31,13 +41,18 @@ public: m_ScoreNumberFrame->X = 15; m_ScoreNumberFrame->Y = 21; + m_FPSCounter = new GUI::FPSCounter(this, "FPSCounter"); + EVENT_SUBSCRIBE_MEMBER(m_EScore, &HUD::OnScore); } private: TextureFrame* m_LevelIndicator = nullptr; TextureFrame* m_ScoreIndicator = nullptr; + NumberFrame* m_AreaNumberFrame = nullptr; + NumberFrame* m_StageNumberFrame = nullptr; NumberFrame* m_ScoreNumberFrame = nullptr; + FPSCounter* m_FPSCounter = nullptr; EventRelay m_EScore; diff --git a/include/Game/PadSystem.h b/include/Game/PadSystem.h index ef76104..39a2582 100755 --- a/include/Game/PadSystem.h +++ b/include/Game/PadSystem.h @@ -73,9 +73,11 @@ private: glm::vec3 m_Acceleration = glm::vec3(0.f, 0.f, 0.f); bool m_Left = false; bool m_Right = false; + bool m_ReplaceBall = false; + bool m_MultiBall = false; float m_Edge = 2.8f; - Components::Transform* m_Transform; - Components::Pad* m_Pad; + Components::Transform* m_Transform = nullptr; + Components::Pad* m_Pad = nullptr; bool m_Pause = false; diff --git a/src/game/Core/EventBroker.cpp b/src/game/Core/EventBroker.cpp index 2c68fd0..ce91fd9 100644 --- a/src/game/Core/EventBroker.cpp +++ b/src/game/Core/EventBroker.cpp @@ -29,32 +29,26 @@ dd::BaseEventRelay::~BaseEventRelay() void dd::EventBroker::Unsubscribe(BaseEventRelay &relay) // ? { - auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName); - if (contextIt == m_ContextRelays.end()) - return; - - auto eventRelays = contextIt->second; - - auto itpair = eventRelays.equal_range(relay.m_EventTypeName); - for (auto it = itpair.first; it != itpair.second; ++it) - { - if (it->second == &relay) - { - relay.m_Broker = nullptr; - eventRelays.erase(it); - break; - } + if (m_IsProcessing) { + m_RelaysToUnsubscribe.push_back(&relay); + } else { + unsubscribeImmediate(relay); } } void dd::EventBroker::Subscribe(BaseEventRelay &relay) { - relay.m_Broker = this; - m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay)); + if (m_IsProcessing) { + m_RelaysToSubscribe.push_back(&relay); + } else { + subscribeImmediate(relay); + } } int dd::EventBroker::Process(std::string contextTypeName) { + m_IsProcessing = true; + auto it = m_ContextRelays.find(contextTypeName); if (it == m_ContextRelays.end()) return 0; @@ -68,14 +62,29 @@ int dd::EventBroker::Process(std::string contextTypeName) std::shared_ptr event = pair.second; auto itpair = relays.equal_range(eventTypeName); - for (auto it2 = itpair.first; it2 != itpair.second; ++it2) + for (auto it2 = itpair.first; it2 != itpair.second; it2++) { - auto relay = it2->second; + std::string name = it2->first; + BaseEventRelay* relay = it2->second; relay->Receive(event); eventsProcessed++; } } + m_IsProcessing = false; + + // Process pending subscriptions + for (auto& r : m_RelaysToSubscribe) { + subscribeImmediate(*r); + } + m_RelaysToSubscribe.clear(); + + // Process pending unsubscriptions + for (auto& r : m_RelaysToUnsubscribe) { + unsubscribeImmediate(*r); + } + m_RelaysToUnsubscribe.clear(); + return eventsProcessed; } @@ -83,4 +92,29 @@ void dd::EventBroker::Swap() { std::swap(m_EventQueueRead, m_EventQueueWrite); m_EventQueueWrite->clear(); + +} + +void dd::EventBroker::subscribeImmediate(dd::BaseEventRelay& relay) +{ + relay.m_Broker = this; + m_ContextRelays[relay.m_ContextTypeName].insert(std::make_pair(relay.m_EventTypeName, &relay)); +} + +void dd::EventBroker::unsubscribeImmediate(dd::BaseEventRelay& relay) +{ + auto contextIt = m_ContextRelays.find(relay.m_ContextTypeName); + if (contextIt == m_ContextRelays.end()) { + return; + } + + auto eventRelays = contextIt->second; + auto itpair = eventRelays.equal_range(relay.m_EventTypeName); + for (auto it = itpair.first; it != itpair.second; ++it) { + if (it->second == &relay) { + relay.m_Broker = nullptr; + eventRelays.erase(it); + break; + } + } } diff --git a/src/tests/EventFixture.h b/src/tests/EventFixture.h index 1548a08..4f78080 100644 --- a/src/tests/EventFixture.h +++ b/src/tests/EventFixture.h @@ -10,7 +10,7 @@ struct EventFixture EventFixture() { this->EventBroker = new dd::EventBroker(); - m_EEventType = decltype(m_EEventType)(std::bind(&OnEvent, this, std::placeholders::_1)); + m_EEventType = decltype(m_EEventType)(std::bind(&EventFixture::OnEvent, this, std::placeholders::_1)); this->EventBroker->Subscribe(m_EEventType); Run(); Check();