diff --git a/AudioPlayerAsync.cpp b/AudioPlayerAsync.cpp new file mode 100644 index 0000000..9a94a56 --- /dev/null +++ b/AudioPlayerAsync.cpp @@ -0,0 +1,90 @@ +#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::stopAsync() { + std::unique_lock lock(mtx); + taskQueue.push([this]() { + //audioPlayerMutex.lock(); + audioPlayer->stop(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + //audioPlayerMutex.unlock(); + }); + cv.notify_one(); +} + +void AudioPlayerAsync::resetAsync() { + std::unique_lock lock(mtx); + taskQueue.push([this]() { + //audioPlayerMutex.lock(); + audioPlayer.reset(); + 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..9f29cef --- /dev/null +++ b/AudioPlayerAsync.h @@ -0,0 +1,48 @@ +#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 stopAsync(); + + 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/BoundaryBox.h b/BoundaryBox.h new file mode 100644 index 0000000..cede401 --- /dev/null +++ b/BoundaryBox.h @@ -0,0 +1,20 @@ +#pragma once +#include "Math.h" + +namespace ZL { +class BoundaryBox { +public: + BoundaryBox(float width, float height) + : halfWidth(width/2) + , halfHeight(height/2) {} + + bool isInside(const Vector3f& position) const { + return (position.v[0] >= -halfWidth && position.v[0] <= halfWidth && + position.v[2] >= -halfHeight && position.v[2] <= halfHeight); + } + +private: + float halfWidth; + float halfHeight; +}; +} diff --git a/GameObjectManager.cpp b/GameObjectManager.cpp index 9dfd612..1c8879a 100644 --- a/GameObjectManager.cpp +++ b/GameObjectManager.cpp @@ -28,7 +28,8 @@ void GameObjectManager::initialize() { testObjMeshMutable.data = testObjMesh; testObjMeshMutable.RefreshVBO(); - textMesh = ZL::LoadFromTextFile("./textures/mesh_first_room.txt"); + //textMesh = ZL::LoadFromTextFile("./textures/mesh_first_room.txt"); + textMesh = ZL::LoadFromTextFile("./oneroom001.txt"); textMesh.Scale(10); textMesh.SwapZandY(); textMesh.RotateByMatrix(QuatToMatrix(QuatFromRotateAroundX(M_PI * 0.5))); @@ -82,7 +83,7 @@ void GameObjectManager::initialize() { Room room_1; - room_1.roomTexture = std::make_shared(CreateTextureDataFromBmp24("./Kitchen_ceramics.bmp")); + room_1.roomTexture = std::make_shared(CreateTextureDataFromBmp24("./Material_Base_color_1001.bmp")); room_1.objects.push_back(ao1); room_1.sound_name = "Symphony No.6 (1st movement).ogg"; room_1.roomLogic = createRoom1Logic(); @@ -98,10 +99,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 +133,17 @@ 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.stopAsync(); + audioPlayerAsync.resetAsync(); + audioPlayerAsync.playMusicAsync(rooms[current_room_index].sound_name); activeObjects = rooms[current_room_index].objects; @@ -211,9 +219,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 +233,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 +246,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 +259,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; @@ -399,26 +412,30 @@ void GameObjectManager::updateScene(size_t ms) { Environment::cameraShift.v[2] -= SPEED * ms; }*/ + Vector3f newPosition = Environment::cameraShift; if (Environment::upPressed) { - Environment::cameraShift.v[0] += directionVector.v[0] * ms; - Environment::cameraShift.v[2] += directionVector.v[1] * ms; + newPosition.v[0] += directionVector.v[0] * ms; + newPosition.v[2] += directionVector.v[1] * ms; } if (Environment::downPressed) { - Environment::cameraShift.v[0] -= directionVector.v[0] * ms; - Environment::cameraShift.v[2] -= directionVector.v[1] * ms; + newPosition.v[0] -= directionVector.v[0] * ms; + newPosition.v[2] -= directionVector.v[1] * ms; } if (Environment::rightPressed) { - Environment::cameraShift.v[2] += directionVector.v[0] * ms; - Environment::cameraShift.v[0] -= directionVector.v[1] * ms; + newPosition.v[2] += directionVector.v[0] * ms; + newPosition.v[0] -= directionVector.v[1] * ms; } if (Environment::leftPressed) { - Environment::cameraShift.v[2] -= directionVector.v[0] * ms; - Environment::cameraShift.v[0] += directionVector.v[1] * ms; + newPosition.v[2] -= directionVector.v[0] * ms; + newPosition.v[0] += directionVector.v[1] * ms; } - Environment::characterPos.v[0] = -Environment::cameraShift.v[0]; - Environment::characterPos.v[1] = -Environment::cameraShift.v[1]; - Environment::characterPos.v[2] = -Environment::cameraShift.v[2]; + Vector3f characterNewPos{-newPosition.v[0], -newPosition.v[1], -newPosition.v[2]}; + // Проверяем, что новая позиция внутри разрешенной зоны + if (walkArea.isInside(characterNewPos)) { + Environment::cameraShift = newPosition; + Environment::characterPos = characterNewPos; + } for (auto& [key, obj] : aoMgr.activeObjectsEntities) { float dist = sqrtf( diff --git a/GameObjectManager.h b/GameObjectManager.h index 7c5eb0f..8d2de46 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" @@ -11,6 +11,11 @@ #endif #include "OpenGlExtensions.h" +#include + +#include "BoundaryBox.h" // Добавляем новый include + + namespace ZL { class GameObjectManager { @@ -47,7 +52,8 @@ public: std::vector activeObjects; std::vector rooms; - std::unique_ptr audioPlayer; + + AudioPlayerAsync audioPlayerAsync; ZL::VertexDataStruct inventoryIconMesh; ZL::VertexRenderStruct inventoryIconMeshMutable; @@ -59,6 +65,8 @@ public: void addRectangle(int x, int y, int width, int height, int r, int g, int b, int borderWidth, int borderR, int borderG, int borderB); + + private: //int animationCounter = 0; int lastMouseX = 0; // Добавляем переменные для хранения позиции мыши @@ -69,6 +77,7 @@ private: Matrix4f projectionModelView, int screenWidth, int screenHeight, int& screenX, int& screenY); + BoundaryBox walkArea{800.0f, 800.0f}; // Изменяем размер с 400 на 800 }; } // namespace ZL 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 abe1ead..2328ac4 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/defaultHideCam.fragment b/defaultHideCam.fragment index 89c7026..a10a442 100644 --- a/defaultHideCam.fragment +++ b/defaultHideCam.fragment @@ -20,7 +20,7 @@ void main() //float distanceToCamera = length(vWorldPos - targetPos); - if ((dotProduct > 0.1) && vWorldPos.y > 30.0) + if ((distanceX > 380.0 || distanceZ > 380.0) && (dotProduct > 0.0) && vWorldPos.y > 10.0) { //color.rgba = vec4(1,0,0,1); discard; diff --git a/shaders/fragment.glsl b/shaders/fragment.glsl new file mode 100644 index 0000000..06e764e --- /dev/null +++ b/shaders/fragment.glsl @@ -0,0 +1,8 @@ +#version 130 + +in vec2 texCoord; +uniform sampler2D textureSampler; + +void main() { + gl_FragColor = texture2D(textureSampler, texCoord); +} diff --git a/shaders/vertex.glsl b/shaders/vertex.glsl new file mode 100644 index 0000000..23d289a --- /dev/null +++ b/shaders/vertex.glsl @@ -0,0 +1,14 @@ +#version 130 + +in vec3 position; +in vec2 texcoord; + +uniform mat4 projection; +uniform mat4 modelView; + +out vec2 texCoord; + +void main() { + gl_Position = projection * modelView * vec4(position, 1.0); + texCoord = texcoord; +} 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) \