From c281070ff6c293b7aa7001d30d7951627845dea7 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sun, 2 Mar 2025 16:54:20 +0300 Subject: [PATCH] Music to separated thread --- AudioPlayerAsync.cpp | 77 ++++++++++++++++++ AudioPlayerAsync.h | 46 +++++++++++ GameObjectManager.cpp | 43 ++++++---- GameObjectManager.h | 8 +- Inventory.cpp | 2 +- Inventory.h | 2 +- RenderSystem.cpp | 5 +- ZeptoLabTest1.vcxproj | 2 + ZeptoLabTest1.vcxproj.filters | 6 ++ ...-Идут-по-земле.ogg => walk.ogg} | Bin start.sh | 3 +- 11 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 AudioPlayerAsync.cpp create mode 100644 AudioPlayerAsync.h rename sounds/{Звук-Идут-по-земле.ogg => walk.ogg} (100%) diff --git a/AudioPlayerAsync.cpp b/AudioPlayerAsync.cpp new file mode 100644 index 0000000..1d09b37 --- /dev/null +++ b/AudioPlayerAsync.cpp @@ -0,0 +1,77 @@ +#include "AudioPlayerAsync.h" + + +AudioPlayerAsync::AudioPlayerAsync() : worker(&AudioPlayerAsync::workerThread, this) {} + +AudioPlayerAsync::~AudioPlayerAsync() { + { + std::unique_lock lock(mtx); + stop = true; + cv.notify_all(); + } + worker.join(); +} + +void AudioPlayerAsync::resetAsync() { + std::unique_lock lock(mtx); + taskQueue.push([this]() { + //audioPlayerMutex.lock(); + audioPlayer = std::make_unique(); + //audioPlayerMutex.unlock(); + }); + cv.notify_one(); +} + +void AudioPlayerAsync::playSoundAsync(std::string soundName) { + + soundNameMutex.lock(); + latestSoundName = soundName; + soundNameMutex.unlock(); + + std::unique_lock lock(mtx); + taskQueue.push([this]() { + //audioPlayerMutex.lock(); + if (audioPlayer) { + audioPlayer->playSound(latestSoundName); + } + //audioPlayerMutex.unlock(); + }); + cv.notify_one(); +} + +void AudioPlayerAsync::playMusicAsync(std::string musicName) { + + musicNameMutex.lock(); + latestMusicName = musicName; + musicNameMutex.unlock(); + + std::unique_lock lock(mtx); + taskQueue.push([this]() { + //audioPlayerMutex.lock(); + if (audioPlayer) { + audioPlayer->playMusic(latestMusicName); + } + //audioPlayerMutex.unlock(); + }); + cv.notify_one(); +} + +void AudioPlayerAsync::workerThread() { + while (true) { + std::function task; + { + std::unique_lock lock(mtx); + cv.wait(lock, [this]() { return !taskQueue.empty() || stop; }); + + if (stop && taskQueue.empty()) { + break; + } + + task = taskQueue.front(); + taskQueue.pop(); + } + + task(); + } +} + diff --git a/AudioPlayerAsync.h b/AudioPlayerAsync.h new file mode 100644 index 0000000..5d88fb0 --- /dev/null +++ b/AudioPlayerAsync.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "cmakeaudioplayer/include/AudioPlayer.hpp" + +class AudioPlayerAsync { +public: + AudioPlayerAsync(); + ~AudioPlayerAsync(); + + void resetAsync(); + + void playSoundAsync(std::string soundName); + + void playMusicAsync(std::string musicName); + + void exit() + { + stop = true; + } + +private: + std::unique_ptr audioPlayer; + //std::mutex audioPlayerMutex; + + std::mutex soundNameMutex; + std::mutex musicNameMutex; + + std::string latestSoundName; + std::string latestMusicName; + + + + std::thread worker; + std::mutex mtx; + std::condition_variable cv; + std::queue> taskQueue; + bool stop = false; + + void workerThread(); + +}; diff --git a/GameObjectManager.cpp b/GameObjectManager.cpp index 81e5914..d2e5430 100644 --- a/GameObjectManager.cpp +++ b/GameObjectManager.cpp @@ -98,10 +98,13 @@ void GameObjectManager::initialize() { activeObjects = rooms[current_room_index].objects; // Initialize audio + /* audioPlayer = std::make_unique(); if (audioPlayer) { audioPlayer->playMusic(rooms[current_room_index].sound_name); - } + }*/ + audioPlayerAsync.resetAsync(); + audioPlayerAsync.playMusicAsync(rooms[current_room_index].sound_name); // Initialize inventory inventoryIconMesh = CreateRect2D( @@ -129,13 +132,16 @@ void GameObjectManager::switch_room(int index){ roomTexturePtr = rooms[current_room_index].roomTexture; - audioPlayer.reset(); // This deletes the current AudioPlayer + + //audioPlayer.reset(); // This deletes the current AudioPlayer // Reinitialize it - audioPlayer = std::make_unique(); + /*audioPlayer = std::make_unique(); if (audioPlayer) { audioPlayer->playMusic(rooms[current_room_index].sound_name); - } + }*/ + audioPlayerAsync.resetAsync(); + audioPlayerAsync.playMusicAsync(rooms[current_room_index].sound_name); activeObjects = rooms[current_room_index].objects; @@ -211,9 +217,11 @@ void GameObjectManager::handleEvent(const SDL_Event& event) { case SDLK_LEFT: case SDLK_a: Environment::leftPressed = true; - if (audioPlayer) { - audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } + /*if (audioPlayer) { + audioPlayer->playSound("walk.ogg"); + }*/ + audioPlayerAsync.playSoundAsync("walk.ogg"); + if (Environment::violaCurrentAnimation == 0) { Environment::violaCurrentAnimation = 1; @@ -223,9 +231,10 @@ void GameObjectManager::handleEvent(const SDL_Event& event) { case SDLK_RIGHT: case SDLK_d: Environment::rightPressed = true; - if (audioPlayer) { - audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } + /*if (audioPlayer) { + audioPlayer->playSound("walk.ogg"); + }*/ + audioPlayerAsync.playSoundAsync("walk.ogg"); if (Environment::violaCurrentAnimation == 0) { Environment::violaCurrentAnimation = 1; @@ -235,9 +244,10 @@ void GameObjectManager::handleEvent(const SDL_Event& event) { case SDLK_UP: case SDLK_w: Environment::upPressed = true; - if (audioPlayer) { - audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } + /*if (audioPlayer) { + audioPlayer->playSound("walk.ogg"); + }*/ + audioPlayerAsync.playSoundAsync("walk.ogg"); if (Environment::violaCurrentAnimation == 0) { Environment::violaCurrentAnimation = 1; @@ -247,9 +257,10 @@ void GameObjectManager::handleEvent(const SDL_Event& event) { case SDLK_DOWN: case SDLK_s: Environment::downPressed = true; - if (audioPlayer) { - audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } + /*if (audioPlayer) { + audioPlayer->playSound("walk.ogg"); + }*/ + audioPlayerAsync.playSoundAsync("walk.ogg"); if (Environment::violaCurrentAnimation == 0) { Environment::violaCurrentAnimation = 1; diff --git a/GameObjectManager.h b/GameObjectManager.h index cae553e..a56bc5a 100644 --- a/GameObjectManager.h +++ b/GameObjectManager.h @@ -1,7 +1,7 @@ #pragma once #include "TextureManager.h" #include "BoneAnimatedModel.h" -#include "cmakeaudioplayer/include/AudioPlayer.hpp" +#include "AudioPlayerAsync.h" #include #include #include "ActiveObject.h" @@ -10,6 +10,7 @@ #include #endif #include "OpenGlExtensions.h" +#include namespace ZL { @@ -47,7 +48,8 @@ public: std::vector activeObjects; std::vector rooms; - std::unique_ptr audioPlayer; + + AudioPlayerAsync audioPlayerAsync; ZL::VertexDataStruct inventoryIconMesh; ZL::VertexRenderStruct inventoryIconMeshMutable; @@ -57,6 +59,8 @@ public: ActiveObjectManager aoMgr; int objects_in_inventory; + + private: //int animationCounter = 0; int lastMouseX = 0; // Добавляем переменные для хранения позиции мыши diff --git a/Inventory.cpp b/Inventory.cpp index 71af814..9e81aa4 100644 --- a/Inventory.cpp +++ b/Inventory.cpp @@ -27,7 +27,7 @@ namespace ZL } - InventoryItem* GetItemByName(const std::string name) + InventoryItem* GetItemByName(const std::string& name) { // Пытаемся найти элемент по ключу auto it = gInventoryMap.find(name); diff --git a/Inventory.h b/Inventory.h index adea97e..6fc6f69 100644 --- a/Inventory.h +++ b/Inventory.h @@ -32,7 +32,7 @@ namespace ZL // Поиск предмета по индексу (возвращает указатель или nullptr) InventoryItem* GetItemByHotkey(int hot_key); InventoryItem* GetItemSelected(bool isSelected); - InventoryItem* GetItemByName(std::string name); + InventoryItem* GetItemByName(const std::string& name); // Вывести весь инвентарь в консоль void PrintInventory(); diff --git a/RenderSystem.cpp b/RenderSystem.cpp index d53e6eb..fb5023e 100644 --- a/RenderSystem.cpp +++ b/RenderSystem.cpp @@ -217,7 +217,10 @@ void RenderSystem::drawUI(const GameObjectManager& gameObjects) { if (ao->activeObjectScreenTexturePtr) { std::cout << "Found activeObjectScreenTexturePtr" << std::endl; int screenX, screenY; - worldToScreenCoordinates(ao->objectPos, currentProjectionModelView, + + Vector3f objectPosPlusShift = ao->objectPos + Vector3f{ 0, -Environment::cameraDefaultVerticalShift, 0 }; + + worldToScreenCoordinates(objectPosPlusShift, currentProjectionModelView, Environment::width, Environment::height, screenX, screenY); renderer.PushMatrix(); // Здесь можно использовать вычисленные screenX, screenY, diff --git a/ZeptoLabTest1.vcxproj b/ZeptoLabTest1.vcxproj index a764aae..a65d219 100755 --- a/ZeptoLabTest1.vcxproj +++ b/ZeptoLabTest1.vcxproj @@ -146,6 +146,7 @@ + @@ -170,6 +171,7 @@ + diff --git a/ZeptoLabTest1.vcxproj.filters b/ZeptoLabTest1.vcxproj.filters index d1b2895..815a529 100755 --- a/ZeptoLabTest1.vcxproj.filters +++ b/ZeptoLabTest1.vcxproj.filters @@ -75,6 +75,9 @@ Source Files + + Source Files + @@ -140,5 +143,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/sounds/Звук-Идут-по-земле.ogg b/sounds/walk.ogg similarity index 100% rename from sounds/Звук-Идут-по-земле.ogg rename to sounds/walk.ogg diff --git a/start.sh b/start.sh index a292265..d309c4d 100755 --- a/start.sh +++ b/start.sh @@ -2,7 +2,8 @@ g++ Game.cpp main.cpp Math.cpp OpenGlExtensions.cpp Physics.cpp Renderer.cpp \ ShaderManager.cpp TextureManager.cpp Utils.cpp BoneAnimatedModel.cpp \ ObjLoader.cpp cmakeaudioplayer/src/AudioPlayer.cpp TextModel.cpp \ Inventory.cpp Environment.cpp GameObjectManager.cpp RenderSystem.cpp QuestScripts.cpp \ - -o sdl_app -O2 -std=c++17 \ + AudioPlayerAsync.cpp \ + -o sdl_app -O2 -std=c++17 -pthread \ -I cmakeaudioplayer/include \ $(pkg-config --cflags --libs sdl2 gl) \ $(pkg-config --cflags --libs vorbis vorbisfile ogg) \