From 17acf0a45ad5ed3ece8668c056ecbb931aebb116 Mon Sep 17 00:00:00 2001 From: Benjamin Kraft Date: Sun, 15 Jan 2023 13:40:35 +0100 Subject: [PATCH] start --- CMakeLists.txt | 11 ++++++- main.cpp | 6 ---- src/Audio.cpp | 16 ++++++++++ src/Audio.h | 14 +++++++++ src/Event.h | 21 +++++++++++++ src/FileManager.cpp | 30 ++++++++++++++++++ src/FileManager.h | 25 +++++++++++++++ src/Listener.h | 17 +++++++++++ src/Player.cpp | 22 ++++++++++++++ src/Player.h | 13 ++++++++ src/Queue.h | 74 +++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 43 ++++++++++++++++++++++++++ 12 files changed, 285 insertions(+), 7 deletions(-) delete mode 100644 main.cpp create mode 100644 src/Audio.cpp create mode 100644 src/Audio.h create mode 100644 src/Event.h create mode 100644 src/FileManager.cpp create mode 100644 src/FileManager.h create mode 100644 src/Listener.h create mode 100644 src/Player.cpp create mode 100644 src/Player.h create mode 100644 src/Queue.h create mode 100644 src/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1aa7d3e..2ceff65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,13 @@ project(EventQueue) set(CMAKE_CXX_STANDARD 23) -add_executable(EventQueue main.cpp) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) + +find_package(Qt6 REQUIRED COMPONENTS Widgets) + +file(GLOB_RECURSE SRC_FILES src/**.cpp) +file(GLOB_RECURSE HEADER_FILES src/**.h) +add_executable(EventQueue ${SRC_FILES} ${HEADER_FILES}) + +target_link_libraries(EventQueue Qt::Widgets) diff --git a/main.cpp b/main.cpp deleted file mode 100644 index 8fbfc65..0000000 --- a/main.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include - -int main() { - std::cout << "Hello, World!" << std::endl; - return 0; -} diff --git a/src/Audio.cpp b/src/Audio.cpp new file mode 100644 index 0000000..33a66ae --- /dev/null +++ b/src/Audio.cpp @@ -0,0 +1,16 @@ +#include "Audio.h" + +#include + +void Audio::update() { + auto cmd = pop(); + + // use volume, soundId to play sound + + delete cmd; +} + +void Audio::playSound(double volume, unsigned int soundId) { + auto command = new AudioCommand {volume, soundId}; + push(command); +} diff --git a/src/Audio.h b/src/Audio.h new file mode 100644 index 0000000..f3e5b2a --- /dev/null +++ b/src/Audio.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Queue.h" + +struct AudioCommand { + double volume; + unsigned soundId; +}; + +class Audio : private Queue { + void update() override; +public: + void playSound(double volume, unsigned soundId); +}; \ No newline at end of file diff --git a/src/Event.h b/src/Event.h new file mode 100644 index 0000000..0c52d2c --- /dev/null +++ b/src/Event.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +struct InputEvent{ + QEvent::Type type; +}; + +struct GameEvent { + int time = 0; + virtual void print() {}; +}; + +struct CoinCollectEvent : GameEvent { + double value = 0; +}; + +struct DamageEvent : GameEvent { + double amount = 0; +}; \ No newline at end of file diff --git a/src/FileManager.cpp b/src/FileManager.cpp new file mode 100644 index 0000000..2ae8e1e --- /dev/null +++ b/src/FileManager.cpp @@ -0,0 +1,30 @@ +#include "FileManager.h" +#include + +void FileManager::update() { + auto cmd = pop(); + cmd->execute(); + delete cmd; +} + +void FileManager::readFile(const std::string &path, const std::function &readCallback) { + auto cmd = new FileReadCommand; + cmd->path = path; + cmd->readCallback = readCallback; + push(cmd); +} + +void FileManager::writeFile(const std::string &path, const std::string &content) { + auto cmd = new FileWriteCommand; + cmd->path = path; + cmd->content = content; + push(cmd); +} + +void FileReadCommand::execute() { + +} + +void FileWriteCommand::execute() { + +} diff --git a/src/FileManager.h b/src/FileManager.h new file mode 100644 index 0000000..c626cf3 --- /dev/null +++ b/src/FileManager.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Queue.h" + +struct FileCommand { + std::string path; + virtual void execute() {}; +}; + +struct FileReadCommand : FileCommand { + std::function readCallback; + void execute() override; +}; + +struct FileWriteCommand : FileCommand { + std::string content; + void execute() override; +}; + +class FileManager : private Queue{ + void update() override; +public: + void readFile(const std::string &path, const std::function &readCallback); + void writeFile(const std::string &path, const std::string &content); +}; \ No newline at end of file diff --git a/src/Listener.h b/src/Listener.h new file mode 100644 index 0000000..0765a61 --- /dev/null +++ b/src/Listener.h @@ -0,0 +1,17 @@ +#pragma once + +template +class Listener { +protected: + template + bool isType(EventType * event) { + return cast(event); + } + template + T * cast(EventType * event) { + return dynamic_cast(event); + } +public: + virtual bool wantsEvent(EventType *) { return true; } + virtual void accept(EventType *) {} +}; \ No newline at end of file diff --git a/src/Player.cpp b/src/Player.cpp new file mode 100644 index 0000000..df0de27 --- /dev/null +++ b/src/Player.cpp @@ -0,0 +1,22 @@ +#include "Player.h" +#include + +bool Player::wantsEvent(GameEvent * event) { + return isType(event) || isType(event); +} + +void Player::accept(GameEvent *event) { + if (auto coinEvent = cast(event)) + OnCoinCollect(coinEvent); + + if (auto dmgEvent = cast(event)) + OnDamage(dmgEvent); +} + +void Player::OnCoinCollect(CoinCollectEvent *event) { + std::cout << event->value << std::endl; +} + +void Player::OnDamage(DamageEvent *event) { + std::cout << event->amount << std::endl; +} diff --git a/src/Player.h b/src/Player.h new file mode 100644 index 0000000..484f416 --- /dev/null +++ b/src/Player.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Listener.h" +#include "Event.h" + +class Player : public Listener { +public: + bool wantsEvent(GameEvent * event) override; + void accept(GameEvent * event) override; +protected: + void OnCoinCollect(CoinCollectEvent * event); + void OnDamage(DamageEvent * event); +}; \ No newline at end of file diff --git a/src/Queue.h b/src/Queue.h new file mode 100644 index 0000000..332bca1 --- /dev/null +++ b/src/Queue.h @@ -0,0 +1,74 @@ +#pragma once + +#include + +#include "Event.h" +#include "Listener.h" +#include +#include +#include + +template +class Queue { +private: + std::thread thread; + std::mutex mutex; + void run() { + while (!QApplication::closingDown()){ + if (!container.empty()) + update(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + }; + virtual void update() {} + std::vector container; +protected: + size_t size() const { + return container.size(); + } + T * pop(){ + mutex.lock(); + T * element = container.back(); + container.pop_back(); + mutex.unlock(); + return element; + } +public: + Queue(){ + thread = std::thread(&Queue::run, this); + } + void push(T * element){ + mutex.lock(); + container.insert(container.begin(), element); + mutex.unlock(); + } +}; + + +template +class EventQueue : protected Queue{ + std::vector *> listeners; + void update() override { + EventType * event = this->pop(); + + for (auto listener : listeners) + if (listener->wantsEvent(event)) + listener->accept(event); + + delete event; + } +public: + template + void submitEvent(T * event){ + this->push(event); + } + void registerListener(Listener * listener){ + listeners.push_back(listener); + } + void unregisterListener(Listener * listener){ + std::remove(listeners.begin(), listeners.end(), listener); + } +}; + +using InputQueue = EventQueue; +using GameQueue = EventQueue; diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..3da9f10 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include "Queue.h" +#include "Audio.h" +#include "FileManager.h" +#include "Player.h" + +using std::cout, std::endl; + +auto audioManager = new Audio; +auto fileManager = new FileManager; +auto gameQueue = new GameQueue; +auto inputQueue = new InputQueue; + +int main(int argc, char * argv[]){ + QApplication app(argc, argv); + + /* + for (int i = 0; i < 100'000; i++) + audioManager->playSound(1, i); + */ + + /* + for (int i = 0; i < 10'000; i++){ + fileManager->readFile("path" + std::to_string(i), [](const std::string& content){ + std::cout << content << std::endl; + }); + fileManager->writeFile("path" + std::to_string(i), "some content" + std::to_string(i)); + } + */ + + auto player = new Player; + gameQueue->registerListener(player); + gameQueue->submitEvent(new CoinCollectEvent); + gameQueue->submitEvent(new DamageEvent); + inputQueue->submitEvent(new InputEvent); + + QWidget window; + window.show(); + + return QApplication::exec(); +} \ No newline at end of file