From bed5ae7a404815756479afe8f5515be421c677bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 18:01:24 +0600 Subject: [PATCH 01/12] added sounds by clicking on button and changed script to compile --- Readme.md | 6 +++++- cmakeaudioplayer/CMakeLists.txt | 1 + cmakeaudioplayer/src/AudioPlayer.cpp | 21 ++++++++++++++------- main.cpp | 19 +++++++++++++++++-- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Readme.md b/Readme.md index 5d8f8f7..c201f67 100644 --- a/Readme.md +++ b/Readme.md @@ -38,6 +38,10 @@ https://github.com/gametutorials/tutorials/blob/master/OpenGL/MD3%20Animation/Ma linux: ``` -g++ Game.cpp main.cpp Math.cpp OpenGlExtensions.cpp Physics.cpp Renderer.cpp ShaderManager.cpp TextureManager.cpp Utils.cpp BoneAnimatedModel.cpp ObjLoader.cpp -o sdl_app -O2 -std=c++14 $(pkg-config --cflags --libs sdl2 gl) +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 -o sdl_app -O2 -std=c++17 \ +-I cmakeaudioplayer/include \ +$(pkg-config --cflags --libs sdl2 gl) \ +$(pkg-config --cflags --libs vorbis vorbisfile ogg) \ +-lopenal ``` \ No newline at end of file diff --git a/cmakeaudioplayer/CMakeLists.txt b/cmakeaudioplayer/CMakeLists.txt index 4e467b4..788d0d8 100644 --- a/cmakeaudioplayer/CMakeLists.txt +++ b/cmakeaudioplayer/CMakeLists.txt @@ -33,3 +33,4 @@ target_link_libraries(audioplayer # Test executable add_executable(test_audio examples/test_audio.cpp) target_link_libraries(test_audio PRIVATE audioplayer stdc++fs) +git add ../../sounds diff --git a/cmakeaudioplayer/src/AudioPlayer.cpp b/cmakeaudioplayer/src/AudioPlayer.cpp index b31d295..4d37c27 100644 --- a/cmakeaudioplayer/src/AudioPlayer.cpp +++ b/cmakeaudioplayer/src/AudioPlayer.cpp @@ -44,22 +44,29 @@ bool AudioPlayer::isOggFile(const std::string& filename) const { } std::string AudioPlayer::findFileInSounds(const std::string& filename) { - // Check relative to executable location first (../../sounds) - std::filesystem::path soundsDir = std::filesystem::current_path() / ".." / ".." / "sounds"; + // Primary search path - "sounds" directory next to executable + std::filesystem::path soundsDir = std::filesystem::current_path() / "sounds"; - // Fallback to ../sounds if not found - std::filesystem::path altSoundsDir = std::filesystem::current_path() / ".." / "sounds"; + // Alternative search paths + std::vector altPaths = { + std::filesystem::current_path() / ".." / "sounds", // One level up + std::filesystem::current_path() / ".." / ".." / "sounds", // Two levels up + "/home/albert/gay-jam/ZeptoLabTest1/sounds" // Absolute path + }; std::cout << "🔍 Searching for \"" << filename << "\" in:\n"; std::cout << " " << soundsDir << "\n"; - std::cout << " " << altSoundsDir << "\n"; if (std::filesystem::exists(soundsDir / filename)) { return (soundsDir / filename).string(); } - if (std::filesystem::exists(altSoundsDir / filename)) { - return (altSoundsDir / filename).string(); + // Try alternative paths + for (const auto& path : altPaths) { + std::cout << " " << path << "\n"; + if (std::filesystem::exists(path / filename)) { + return (path / filename).string(); + } } throw std::runtime_error("❌ File not found: " + filename); diff --git a/main.cpp b/main.cpp index cbfa8f4..d2013ff 100755 --- a/main.cpp +++ b/main.cpp @@ -18,6 +18,7 @@ #include "TextModel.h" #include "Inventory.h" +#include "cmakeaudioplayer/include/AudioPlayer.hpp" #include namespace ZL @@ -32,11 +33,11 @@ namespace ZL Vector4f clipCoords = MultMatrixVector(projectionModelView, inx); - // + // ������������� ������� float ndcX = clipCoords.v[0] / clipCoords.v[3]; float ndcY = clipCoords.v[1] / clipCoords.v[3]; - // NDC + // ����������� NDC � �������� ���������� screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth); //screenY = (int)((1.0f - ndcY) * 0.5f * screenHeight); screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight); @@ -108,6 +109,9 @@ namespace ZL VertexRenderStruct coneMeshMutable; std::vector activeObjects; + + // Add AudioPlayer instance + std::unique_ptr audioPlayer; } static SDL_Window* window = NULL; @@ -397,6 +401,11 @@ namespace ZL std::cout << "\nAfter removal:\n"; ZL::PrintInventory(); + + // Initialize audio player + GameObjects::audioPlayer = std::make_unique(); + + /// } void render() { @@ -461,6 +470,12 @@ namespace ZL case SDLK_s: Env::downPressed = true; break; + case SDLK_SPACE: + // Play the symphony when space is pressed + if (GameObjects::audioPlayer) { + GameObjects::audioPlayer->playFromSoundsDir("Symphony No.6 (1st movement).ogg"); + } + break; } } From 27ecda3124d7354794615e7789a9a39a12086691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 18:20:50 +0600 Subject: [PATCH 02/12] added sounds and music in main cpp by cliking wasd or arrow will play sound of steps and music in setup start playing --- cmakeaudioplayer/include/AudioPlayer.hpp | 16 +++- cmakeaudioplayer/src/AudioPlayer.cpp | 91 ++++++++++++++----- main.cpp | 23 ++++- sounds/Звук-Идут-по-земле.ogg | Bin 0 -> 8986 bytes 4 files changed, 97 insertions(+), 33 deletions(-) create mode 100644 sounds/Звук-Идут-по-земле.ogg diff --git a/cmakeaudioplayer/include/AudioPlayer.hpp b/cmakeaudioplayer/include/AudioPlayer.hpp index c8e2d12..b1d23f1 100644 --- a/cmakeaudioplayer/include/AudioPlayer.hpp +++ b/cmakeaudioplayer/include/AudioPlayer.hpp @@ -12,18 +12,26 @@ public: AudioPlayer(); ~AudioPlayer(); - bool playFromSoundsDir(const std::string& filename); + // Для музыки с зацикливанием (если filename пустой - продолжает играть текущую) + bool playMusic(const std::string& filename = ""); + + // Для одноразовых звуковых эффектов + bool playSound(const std::string& filename); + void stop(); bool isPlaying() const; private: ALCdevice* device; ALCcontext* context; - ALuint source; - ALuint buffer; + ALuint musicSource; // Источник для музыки + ALuint soundSource; // Источник для звуков + ALuint musicBuffer; // Буфер для музыки + ALuint soundBuffer; // Буфер для звуков bool playing; + std::string currentMusic; // Хранит имя текущего музыкального файла - std::vector loadOgg(const std::string& filename); + std::vector loadOgg(const std::string& filename, ALuint buffer); std::string findFileInSounds(const std::string& filename); bool isOggFile(const std::string& filename) const; }; diff --git a/cmakeaudioplayer/src/AudioPlayer.cpp b/cmakeaudioplayer/src/AudioPlayer.cpp index 4d37c27..e650ea9 100644 --- a/cmakeaudioplayer/src/AudioPlayer.cpp +++ b/cmakeaudioplayer/src/AudioPlayer.cpp @@ -6,7 +6,8 @@ #include #include -AudioPlayer::AudioPlayer() : device(nullptr), context(nullptr), source(0), buffer(0), playing(false) { +AudioPlayer::AudioPlayer() : device(nullptr), context(nullptr), + musicSource(0), soundSource(0), musicBuffer(0), soundBuffer(0), playing(false) { device = alcOpenDevice(nullptr); if (!device) { throw std::runtime_error("Failed to open audio device"); @@ -19,15 +20,21 @@ AudioPlayer::AudioPlayer() : device(nullptr), context(nullptr), source(0), buffe } alcMakeContextCurrent(context); - alGenSources(1, &source); - alGenBuffers(1, &buffer); + alGenSources(1, &musicSource); + alGenSources(1, &soundSource); + alGenBuffers(1, &musicBuffer); + alGenBuffers(1, &soundBuffer); } AudioPlayer::~AudioPlayer() { - if (source) - alDeleteSources(1, &source); - if (buffer) - alDeleteBuffers(1, &buffer); + if (musicSource) + alDeleteSources(1, &musicSource); + if (soundSource) + alDeleteSources(1, &soundSource); + if (musicBuffer) + alDeleteBuffers(1, &musicBuffer); + if (soundBuffer) + alDeleteBuffers(1, &soundBuffer); if (context) { alcMakeContextCurrent(nullptr); @@ -72,7 +79,7 @@ std::string AudioPlayer::findFileInSounds(const std::string& filename) { throw std::runtime_error("❌ File not found: " + filename); } -std::vector AudioPlayer::loadOgg(const std::string& filename) { +std::vector AudioPlayer::loadOgg(const std::string& filename, ALuint buffer) { FILE* file = fopen(filename.c_str(), "rb"); if (!file) { throw std::runtime_error("Cannot open file: " + filename); @@ -108,45 +115,79 @@ std::vector AudioPlayer::loadOgg(const std::string& filename) { return audioData; } -bool AudioPlayer::playFromSoundsDir(const std::string& filename) { +bool AudioPlayer::playMusic(const std::string& filename) { try { + // Если filename пустой, просто проверяем играет ли музыка + if (filename.empty()) { + if (!isPlaying()) { + alSourcei(musicSource, AL_LOOPING, AL_TRUE); // Включаем зацикливание + alSourcePlay(musicSource); + } + return true; + } + + // Если filename не пустой, загружаем новую музыку if (!isOggFile(filename)) { - std::cerr << "❌ Error: File must be an .ogg file\n"; + std::cerr << "❌ Error: Music file must be an .ogg file\n"; return false; } std::string fullPath = findFileInSounds(filename); - std::cout << "✅ Found file: " << fullPath << "\n"; + std::cout << "✅ Found music file: " << fullPath << "\n"; - auto audioData = loadOgg(fullPath); - alSourcei(source, AL_BUFFER, buffer); + // Останавливаем текущую музыку + alSourceStop(musicSource); - alGetError(); // Clear any previous errors + // Загружаем и настраиваем новую музыку + loadOgg(fullPath, musicBuffer); + alSourcei(musicSource, AL_BUFFER, musicBuffer); + alSourcei(musicSource, AL_LOOPING, AL_TRUE); // Включаем зацикливание - std::cout << "▶️ Starting playback...\n"; - alSourcePlay(source); - - ALenum error = alGetError(); - if (error != AL_NO_ERROR) { - std::cerr << "❌ OpenAL error: " << error << std::endl; - return false; - } + std::cout << "▶️ Starting music playback...\n"; + alSourcePlay(musicSource); + currentMusic = filename; playing = true; return true; } catch (const std::exception& e) { - std::cerr << "❌ Error: " << e.what() << std::endl; + std::cerr << "❌ Error playing music: " << e.what() << std::endl; + return false; + } +} + +bool AudioPlayer::playSound(const std::string& filename) { + try { + if (!isOggFile(filename)) { + std::cerr << "❌ Error: Sound file must be an .ogg file\n"; + return false; + } + + std::string fullPath = findFileInSounds(filename); + std::cout << "✅ Found sound file: " << fullPath << "\n"; + + // Загружаем и настраиваем звук + loadOgg(fullPath, soundBuffer); + alSourcei(soundSource, AL_BUFFER, soundBuffer); + alSourcei(soundSource, AL_LOOPING, AL_FALSE); // Выключаем зацикливание + + std::cout << "▶️ Playing sound effect...\n"; + alSourcePlay(soundSource); + + return true; + } catch (const std::exception& e) { + std::cerr << "❌ Error playing sound: " << e.what() << std::endl; return false; } } void AudioPlayer::stop() { - alSourceStop(source); + alSourceStop(musicSource); + alSourceStop(soundSource); playing = false; } bool AudioPlayer::isPlaying() const { ALint state; - alGetSourcei(source, AL_SOURCE_STATE, &state); + alGetSourcei(musicSource, AL_SOURCE_STATE, &state); return state == AL_PLAYING; } diff --git a/main.cpp b/main.cpp index d2013ff..33f4340 100755 --- a/main.cpp +++ b/main.cpp @@ -402,8 +402,11 @@ namespace ZL std::cout << "\nAfter removal:\n"; ZL::PrintInventory(); - // Initialize audio player + // Initialize audio player and start background music GameObjects::audioPlayer = std::make_unique(); + if (GameObjects::audioPlayer) { + GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); + } /// } @@ -457,25 +460,37 @@ namespace ZL case SDLK_LEFT: case SDLK_a: Env::leftPressed = true; + if (GameObjects::audioPlayer) { + GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } break; case SDLK_RIGHT: case SDLK_d: Env::rightPressed = true; + if (GameObjects::audioPlayer) { + GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } break; case SDLK_UP: case SDLK_w: Env::upPressed = true; + if (GameObjects::audioPlayer) { + GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } break; case SDLK_DOWN: case SDLK_s: Env::downPressed = true; + if (GameObjects::audioPlayer) { + GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } break; case SDLK_SPACE: // Play the symphony when space is pressed if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playFromSoundsDir("Symphony No.6 (1st movement).ogg"); - } - break; + GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); + } + break; } } diff --git a/sounds/Звук-Идут-по-земле.ogg b/sounds/Звук-Идут-по-земле.ogg new file mode 100644 index 0000000000000000000000000000000000000000..fca9763c534f58ab987c19af6e1aba8ac71fdc87 GIT binary patch literal 8986 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 oxCk@bSwT7=jnn>%^!;5U@9l0=^Mt&&$RE Date: Sat, 1 Mar 2025 19:04:49 +0600 Subject: [PATCH 03/12] added inventory testing buttons I to add items O to delete last items in inventory and p to get info about inventory --- main.cpp | 209 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 131 insertions(+), 78 deletions(-) diff --git a/main.cpp b/main.cpp index 33f4340..5168fa8 100755 --- a/main.cpp +++ b/main.cpp @@ -112,6 +112,12 @@ namespace ZL // Add AudioPlayer instance std::unique_ptr audioPlayer; + + // Добавляем структуры для иконок инвентаря + VertexDataStruct inventoryIconMesh; + VertexRenderStruct inventoryIconMeshMutable; + const float INVENTORY_ICON_SIZE = 32.0f; // Размер иконки в пикселях + const float INVENTORY_MARGIN = 10.0f; // Отступ от края экрана } static SDL_Window* window = NULL; @@ -213,6 +219,18 @@ namespace ZL } } + // Отрисовка иконок инвентаря + const auto& inventory = ReturnInventory(); + for (size_t i = 0; i < inventory.size(); ++i) { + renderer.PushMatrix(); + float xPos = Env::width - GameObjects::INVENTORY_MARGIN - GameObjects::INVENTORY_ICON_SIZE; + float yPos = GameObjects::INVENTORY_MARGIN + i * (GameObjects::INVENTORY_ICON_SIZE + GameObjects::INVENTORY_MARGIN); + renderer.TranslateMatrix(Vector3f{xPos, yPos, 0.0f}); + glBindTexture(GL_TEXTURE_2D, inventory[i].texture->getTexID()); + renderer.DrawVertexRenderStruct(GameObjects::inventoryIconMeshMutable); + renderer.PopMatrix(); + } + renderer.PopMatrix(); renderer.PopProjectionMatrix(); @@ -393,14 +411,14 @@ namespace ZL ZL::AddItemToInventory("RoomCeramics", roomTexturePtr); ZL::AddItemToInventory("Cone", coneTexturePtr); - std::cout << "Before removal:\n"; + // std::cout << "Before removal:\n"; ZL::PrintInventory(); // Удаляем "Cone" из инвентаря - ZL::RemoveItemFromInventory("Cone"); + // ZL::RemoveItemFromInventory("Cone"); - std::cout << "\nAfter removal:\n"; - ZL::PrintInventory(); + // std::cout << "\nAfter removal:\n"; + // ZL::PrintInventory(); // Initialize audio player and start background music GameObjects::audioPlayer = std::make_unique(); @@ -408,6 +426,15 @@ namespace ZL GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); } + // Инициализация меша иконки инвентаря + GameObjects::inventoryIconMesh = CreateRect2D( + {0.0f, 0.0f}, + {GameObjects::INVENTORY_ICON_SIZE/2, GameObjects::INVENTORY_ICON_SIZE/2}, + 0.5f + ); + GameObjects::inventoryIconMeshMutable.AssignFrom(GameObjects::inventoryIconMesh); + GameObjects::inventoryIconMeshMutable.RefreshVBO(); + /// } @@ -427,98 +454,124 @@ namespace ZL } - void update() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - ExitGameLoop = true; - } - if (event.type == SDL_MOUSEBUTTONDOWN) { - static int x = 0; + void update() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + ExitGameLoop = true; + } + if (event.type == SDL_MOUSEBUTTONDOWN) { + static int x = 0; - GameObjects::bx.Interpolate(x); - x = x + 2; - } - if (event.type == SDL_MOUSEWHEEL) { + GameObjects::bx.Interpolate(x); + x = x + 2; + } + if (event.type == SDL_MOUSEWHEEL) { - static const float zoomstep = 1.0f; - if (event.wheel.y > 0) { - // ��������� ����� - ����������� zoom - Env::zoom -= zoomstep; - } - else if (event.wheel.y < 0) { - // ��������� ���� - ��������� zoom - Env::zoom += zoomstep; - } - // ������������ zoom, ����� �� �� ���� ������������� - if (Env::zoom < zoomstep) { - Env::zoom = zoomstep; - } - } - if (event.type == SDL_KEYDOWN) { - switch (event.key.keysym.sym) { - case SDLK_LEFT: - case SDLK_a: - Env::leftPressed = true; - if (GameObjects::audioPlayer) { + static const float zoomstep = 1.0f; + if (event.wheel.y > 0) { + // ��������� ����� - ����������� zoom + Env::zoom -= zoomstep; + } + else if (event.wheel.y < 0) { + // ��������� ���� - ��������� zoom + Env::zoom += zoomstep; + } + // ������������ zoom, ����� �� �� ���� ������������� + if (Env::zoom < zoomstep) { + Env::zoom = zoomstep; + } + } + if (event.type == SDL_KEYDOWN) { + switch (event.key.keysym.sym) { + case SDLK_LEFT: + case SDLK_a: + Env::leftPressed = true; + if (GameObjects::audioPlayer) { GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); } - break; - case SDLK_RIGHT: - case SDLK_d: - Env::rightPressed = true; - if (GameObjects::audioPlayer) { + break; + case SDLK_RIGHT: + case SDLK_d: + Env::rightPressed = true; + if (GameObjects::audioPlayer) { GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); } - break; - case SDLK_UP: - case SDLK_w: - Env::upPressed = true; - if (GameObjects::audioPlayer) { + break; + case SDLK_UP: + case SDLK_w: + Env::upPressed = true; + if (GameObjects::audioPlayer) { GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); } - break; - case SDLK_DOWN: - case SDLK_s: - Env::downPressed = true; - if (GameObjects::audioPlayer) { + break; + case SDLK_DOWN: + case SDLK_s: + Env::downPressed = true; + if (GameObjects::audioPlayer) { GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); } - break; - case SDLK_SPACE: + break; + case SDLK_SPACE: // Play the symphony when space is pressed if (GameObjects::audioPlayer) { GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); } break; - } + // Добавляем тестовые клавиши + case SDLK_i: // Добавить предмет по нажатию I + { + static int testItemCount = 0; + auto testTexture = std::make_shared(CreateTextureDataFromBmp24("./book03.bmp")); + AddItemToInventory("TestItem_" + std::to_string(testItemCount++), testTexture); + std::cout << "Added test item to inventory\n"; + PrintInventory(); + } + break; + + case SDLK_o: // Удалить последний предмет по нажатию O + { + auto inventory = ReturnInventory(); + if (!inventory.empty()) { + RemoveItemFromInventory(inventory.back().name); + std::cout << "Removed last item from inventory\n"; + PrintInventory(); + } + } + break; + + case SDLK_p: // Вывести текущий инвентарь по нажатию P + std::cout << "\nCurrent inventory contents:\n"; + PrintInventory(); + break; + } - } + } - if (event.type == SDL_KEYUP) { - switch (event.key.keysym.sym) { - case SDLK_LEFT: - case SDLK_a: - Env::leftPressed = false; - break; - case SDLK_RIGHT: - case SDLK_d: - Env::rightPressed = false; - break; - case SDLK_UP: - case SDLK_w: - Env::upPressed = false; - break; - case SDLK_DOWN: - case SDLK_s: - Env::downPressed = false; - break; - } - } - } + if (event.type == SDL_KEYUP) { + switch (event.key.keysym.sym) { + case SDLK_LEFT: + case SDLK_a: + Env::leftPressed = false; + break; + case SDLK_RIGHT: + case SDLK_d: + Env::rightPressed = false; + break; + case SDLK_UP: + case SDLK_w: + Env::upPressed = false; + break; + case SDLK_DOWN: + case SDLK_s: + Env::downPressed = false; + break; + } + } + } - render(); - } + render(); + } }; From 613d809b43ad9fea3d66503f19c525423244eabb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 19:06:42 +0600 Subject: [PATCH 04/12] deleted buttons for testing --- main.cpp | 30 +----------------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/main.cpp b/main.cpp index 5168fa8..89566be 100755 --- a/main.cpp +++ b/main.cpp @@ -513,39 +513,11 @@ namespace ZL } break; case SDLK_SPACE: - // Play the symphony when space is pressed - if (GameObjects::audioPlayer) { + if (GameObjects::audioPlayer) { GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); } break; - // Добавляем тестовые клавиши - case SDLK_i: // Добавить предмет по нажатию I - { - static int testItemCount = 0; - auto testTexture = std::make_shared(CreateTextureDataFromBmp24("./book03.bmp")); - AddItemToInventory("TestItem_" + std::to_string(testItemCount++), testTexture); - std::cout << "Added test item to inventory\n"; - PrintInventory(); - } - break; - - case SDLK_o: // Удалить последний предмет по нажатию O - { - auto inventory = ReturnInventory(); - if (!inventory.empty()) { - RemoveItemFromInventory(inventory.back().name); - std::cout << "Removed last item from inventory\n"; - PrintInventory(); - } - } - break; - - case SDLK_p: // Вывести текущий инвентарь по нажатию P - std::cout << "\nCurrent inventory contents:\n"; - PrintInventory(); - break; } - } if (event.type == SDL_KEYUP) { From 666bfc1b377783cae57e4fac793bbd8db2b62d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 19:16:26 +0600 Subject: [PATCH 05/12] added sh file for start in linux --- GameWorld.cpp | 0 GameWorld.h | 0 InputManager.cpp | 0 InputManager.h | 0 start.sh | 7 +++++++ 5 files changed, 7 insertions(+) create mode 100644 GameWorld.cpp create mode 100644 GameWorld.h create mode 100644 InputManager.cpp create mode 100644 InputManager.h create mode 100755 start.sh diff --git a/GameWorld.cpp b/GameWorld.cpp new file mode 100644 index 0000000..e69de29 diff --git a/GameWorld.h b/GameWorld.h new file mode 100644 index 0000000..e69de29 diff --git a/InputManager.cpp b/InputManager.cpp new file mode 100644 index 0000000..e69de29 diff --git a/InputManager.h b/InputManager.h new file mode 100644 index 0000000..e69de29 diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..7b779b7 --- /dev/null +++ b/start.sh @@ -0,0 +1,7 @@ +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 -o sdl_app -O2 -std=c++17 \ +-I cmakeaudioplayer/include \ +$(pkg-config --cflags --libs sdl2 gl) \ +$(pkg-config --cflags --libs vorbis vorbisfile ogg) \ +-lopenal + +./sdl_app \ No newline at end of file From e2af375aa021b78a5f8764e980969f9f66da3f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 19:18:42 +0600 Subject: [PATCH 06/12] starting refactoring main.cpp --- GameWorld.cpp | 23 +++++++++++++++++++++++ GameWorld.h | 18 ++++++++++++++++++ InputManager.cpp | 27 +++++++++++++++++++++++++++ InputManager.h | 17 +++++++++++++++++ main.cpp | 8 ++++++-- 5 files changed, 91 insertions(+), 2 deletions(-) diff --git a/GameWorld.cpp b/GameWorld.cpp index e69de29..352154d 100644 --- a/GameWorld.cpp +++ b/GameWorld.cpp @@ -0,0 +1,23 @@ +#include "GameWorld.h" +#include "InputManager.h" + +namespace ZL { + GameWorld& GameWorld::getInstance() { + static GameWorld instance; + return instance; + } + + void GameWorld::update(float deltaTime) { + auto& input = InputManager::getInstance(); + + // Update game state based on input + if (input.isKeyPressed(SDL_SCANCODE_W)) { + // Move forward + } + // ... handle other game logic ... + } + + void GameWorld::addObject(const Vector3f& position) { + mGameObjects.push_back(position); + } +} diff --git a/GameWorld.h b/GameWorld.h index e69de29..475acd9 100644 --- a/GameWorld.h +++ b/GameWorld.h @@ -0,0 +1,18 @@ +#pragma once +#include "Vector3f.h" +#include +#include + +namespace ZL { + class GameWorld { + public: + static GameWorld& getInstance(); + void update(float deltaTime); + void addObject(const Vector3f& position); + // ...other game world related methods... + + private: + GameWorld() = default; + std::vector mGameObjects; + }; +} diff --git a/InputManager.cpp b/InputManager.cpp index e69de29..0addbde 100644 --- a/InputManager.cpp +++ b/InputManager.cpp @@ -0,0 +1,27 @@ +#include "InputManager.h" + +namespace ZL { + InputManager& InputManager::getInstance() { + static InputManager instance; + return instance; + } + + void InputManager::processInput() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + mShouldQuit = true; + } + else if (event.type == SDL_KEYDOWN) { + mKeys[event.key.keysym.scancode] = true; + } + else if (event.type == SDL_KEYUP) { + mKeys[event.key.keysym.scancode] = false; + } + } + } + + bool InputManager::isKeyPressed(SDL_Scancode key) const { + return mKeys[key]; + } +} diff --git a/InputManager.h b/InputManager.h index e69de29..035ff06 100644 --- a/InputManager.h +++ b/InputManager.h @@ -0,0 +1,17 @@ +#pragma once +#include + +namespace ZL { + class InputManager { + public: + static InputManager& getInstance(); + void processInput(); + bool isKeyPressed(SDL_Scancode key) const; + bool shouldQuit() const { return mShouldQuit; } + + private: + InputManager() = default; + bool mKeys[SDL_NUM_SCANCODES] = {false}; + bool mShouldQuit = false; + }; +} diff --git a/main.cpp b/main.cpp index 89566be..6de058a 100755 --- a/main.cpp +++ b/main.cpp @@ -413,7 +413,9 @@ namespace ZL // std::cout << "Before removal:\n"; ZL::PrintInventory(); - + 21s  +    ~/g/ZeptoLabTest1    Albert ⇣2 +5  git commit -m "added sh file for start in linux" + [Albert 666bfc1] added sh file for start in linux // Удаляем "Cone" из инвентаря // ZL::RemoveItemFromInventory("Cone"); @@ -534,7 +536,9 @@ namespace ZL case SDLK_w: Env::upPressed = false; break; - case SDLK_DOWN: + case SDLK_DOWN: 21s  +    ~/g/ZeptoLabTest1    Albert ⇣2 +5  git commit -m "added sh file for start in linux" + [Albert 666bfc1] added sh file for start in linux case SDLK_s: Env::downPressed = false; break; From b6684f7929fdaaefdea214160413f6e35b090867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 19:22:19 +0600 Subject: [PATCH 07/12] refactored --- main.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/main.cpp b/main.cpp index 6de058a..a0fb1c5 100755 --- a/main.cpp +++ b/main.cpp @@ -411,16 +411,7 @@ namespace ZL ZL::AddItemToInventory("RoomCeramics", roomTexturePtr); ZL::AddItemToInventory("Cone", coneTexturePtr); - // std::cout << "Before removal:\n"; ZL::PrintInventory(); - 21s  -    ~/g/ZeptoLabTest1    Albert ⇣2 +5  git commit -m "added sh file for start in linux" - [Albert 666bfc1] added sh file for start in linux - // Удаляем "Cone" из инвентаря - // ZL::RemoveItemFromInventory("Cone"); - - // std::cout << "\nAfter removal:\n"; - // ZL::PrintInventory(); // Initialize audio player and start background music GameObjects::audioPlayer = std::make_unique(); @@ -536,9 +527,7 @@ namespace ZL case SDLK_w: Env::upPressed = false; break; - case SDLK_DOWN: 21s  -    ~/g/ZeptoLabTest1    Albert ⇣2 +5  git commit -m "added sh file for start in linux" - [Albert 666bfc1] added sh file for start in linux + case SDLK_DOWN: case SDLK_s: Env::downPressed = false; break; From dbffcf5f041ef006ce8ce9b7980a094b934947b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 20:53:11 +0600 Subject: [PATCH 08/12] refacored some parts of main.sh --- ActiveObject.h | 17 ++++++++++++ Environment.cpp | 14 ++++++++++ Environment.h | 18 +++++++++++++ Game.h | 39 ++++++++++++++++++++------- GameObjectManager.cpp | 12 +++++++++ GameObjectManager.h | 41 +++++++++++++++++++++++++++++ main.cpp | 61 +++++++++++-------------------------------- start.sh | 14 ++++++---- 8 files changed, 156 insertions(+), 60 deletions(-) create mode 100644 ActiveObject.h create mode 100644 Environment.cpp create mode 100644 Environment.h create mode 100644 GameObjectManager.cpp create mode 100644 GameObjectManager.h diff --git a/ActiveObject.h b/ActiveObject.h new file mode 100644 index 0000000..bc3dc94 --- /dev/null +++ b/ActiveObject.h @@ -0,0 +1,17 @@ +#pragma once +#include "TextureManager.h" +#include "Math.h" +#include + +struct ActiveObject { + std::shared_ptr activeObjectTexturePtr; + ZL::VertexDataStruct activeObjectMesh; + ZL::VertexRenderStruct activeObjectMeshMutable; + + std::shared_ptr activeObjectScreenTexturePtr; + ZL::VertexDataStruct activeObjectScreenMesh; + ZL::VertexRenderStruct activeObjectScreenMeshMutable; + + ZL::Vector3f objectPos; + bool highlighted = false; +}; diff --git a/Environment.cpp b/Environment.cpp new file mode 100644 index 0000000..0bb9b23 --- /dev/null +++ b/Environment.cpp @@ -0,0 +1,14 @@ +#include "Environment.h" + +int Environment::windowHeaderHeight = 0; +int Environment::width = 0; +int Environment::height = 0; +float Environment::zoom = 10.0f; + +bool Environment::leftPressed = false; +bool Environment::rightPressed = false; +bool Environment::upPressed = false; +bool Environment::downPressed = false; + +Vector3f Environment::cameraShift = {0, 0, 0}; +Vector3f Environment::characterPos = {0, 0, 0}; diff --git a/Environment.h b/Environment.h new file mode 100644 index 0000000..f0dc366 --- /dev/null +++ b/Environment.h @@ -0,0 +1,18 @@ +#pragma once +#include "Math.h" + +class Environment { +public: + static int windowHeaderHeight; + static int width; + static int height; + static float zoom; + + static bool leftPressed; + static bool rightPressed; + static bool upPressed; + static bool downPressed; + + static ZL::Vector3f cameraShift; + static ZL::Vector3f characterPos; +}; diff --git a/Game.h b/Game.h index a76b369..66c4804 100755 --- a/Game.h +++ b/Game.h @@ -1,14 +1,35 @@ #pragma once -#include "Math.h" -#include "Physics.h" -#include "TextureManager.h" +#include +#include "GameObjectManager.h" #include "Renderer.h" -#include "AnimatedModel.h" -#include "BoneAnimatedModel.h" -#include +#include "Environment.h" -namespace ZL -{ +class Game { +public: + Game(); + ~Game(); + + void setup(); + void run(); + void update(); + void render(); + + bool shouldExit() const { return exitGameLoop; } -} \ No newline at end of file +private: + void processTickCount(); + void drawScene(); + + SDL_Window* window; + SDL_GLContext glContext; + ZL::Renderer renderer; + GameObjectManager gameObjects; + + bool exitGameLoop; + size_t newTickCount; + size_t lastTickCount; + + static const size_t CONST_TIMER_INTERVAL = 10; + static const size_t CONST_MAX_TIME_INTERVAL = 1000; +}; \ No newline at end of file diff --git a/GameObjectManager.cpp b/GameObjectManager.cpp new file mode 100644 index 0000000..5577188 --- /dev/null +++ b/GameObjectManager.cpp @@ -0,0 +1,12 @@ +#include "GameObjectManager.h" + +const float GameObjectManager::INVENTORY_ICON_SIZE = 32.0f; +const float GameObjectManager::INVENTORY_MARGIN = 10.0f; + +void GameObjectManager::initialize() { + // Implementation coming from main.cpp setup() +} + +void GameObjectManager::update() { + // Implementation coming from main.cpp update() +} diff --git a/GameObjectManager.h b/GameObjectManager.h new file mode 100644 index 0000000..1e56e1f --- /dev/null +++ b/GameObjectManager.h @@ -0,0 +1,41 @@ +#pragma once +#include "TextureManager.h" +#include "BoneAnimatedModel.h" +#include "cmakeaudioplayer/include/AudioPlayer.hpp" +#include +#include +#include "ActiveObject.h" + +class GameObjectManager { +public: + void initialize(); + void update(); + + std::shared_ptr testObjTexturePtr; + std::shared_ptr roomTexturePtr; + std::shared_ptr coneTexturePtr; + + ZL::VertexDataStruct colorCubeMesh; + ZL::VertexRenderStruct colorCubeMeshMutable; + + ZL::VertexDataStruct testObjMesh; + ZL::VertexRenderStruct testObjMeshMutable; + + ZL::BoneSystem bx; + ZL::VertexRenderStruct bxMutable; + + ZL::VertexDataStruct textMesh; + ZL::VertexRenderStruct textMeshMutable; + + ZL::VertexDataStruct coneMesh; + ZL::VertexRenderStruct coneMeshMutable; + + std::vector activeObjects; + std::unique_ptr audioPlayer; + + ZL::VertexDataStruct inventoryIconMesh; + ZL::VertexRenderStruct inventoryIconMeshMutable; + + static const float INVENTORY_ICON_SIZE; + static const float INVENTORY_MARGIN; +}; diff --git a/main.cpp b/main.cpp index a0fb1c5..e13e50b 100755 --- a/main.cpp +++ b/main.cpp @@ -540,57 +540,26 @@ namespace ZL }; -int main(int argc, char* argv[]) -{ +#include "Game.h" - constexpr int CONST_WIDTH = 1280; - constexpr int CONST_HEIGHT = 720; +int main(int argc, char* argv[]) { + constexpr int CONST_WIDTH = 1280; + constexpr int CONST_HEIGHT = 720; - ZL::Env::width = CONST_WIDTH; - ZL::Env::height = CONST_HEIGHT; + Environment::width = CONST_WIDTH; + Environment::height = CONST_HEIGHT; + + Game game; + game.setup(); #ifdef EMSCRIPTEN - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_Renderer* renderer = NULL; - SDL_CreateWindowAndRenderer(CONST_WIDTH, CONST_HEIGHT, SDL_WINDOW_OPENGL, &ZL::window, &renderer); + emscripten_set_main_loop([]() { game.update(); }, 0, 1); #else - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { - SDL_Log("Failed to initialize SDL: %s", SDL_GetError()); - return 1; - } - - - // Use a core profile setup. - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - ZL::window = SDL_CreateWindow("Jumping Bird", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, CONST_WIDTH, CONST_HEIGHT, SDL_WINDOW_OPENGL); -#endif - //todo - ZL::Env::windowHeaderHeight = 0; - - ZL::gl_context = SDL_GL_CreateContext(ZL::window); - - ZL::CheckGlError(); - - ZL::setup(); -#ifdef EMSCRIPTEN - // register update as callback - emscripten_set_main_loop(ZL::update, 0, 1); -#else - while (!ZL::ExitGameLoop) { - - ZL::update(); - SDL_Delay(2); - - } - SDL_GL_DeleteContext(ZL::gl_context); - SDL_DestroyWindow(ZL::window); - SDL_Quit(); - - exit(0); + while (!game.shouldExit()) { + game.update(); + SDL_Delay(2); + } #endif + return 0; } diff --git a/start.sh b/start.sh index 7b779b7..65dd930 100755 --- a/start.sh +++ b/start.sh @@ -1,7 +1,11 @@ -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 -o sdl_app -O2 -std=c++17 \ --I cmakeaudioplayer/include \ -$(pkg-config --cflags --libs sdl2 gl) \ -$(pkg-config --cflags --libs vorbis vorbisfile ogg) \ --lopenal +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 \ + -o sdl_app -O2 -std=c++17 \ + -I cmakeaudioplayer/include \ + $(pkg-config --cflags --libs sdl2 gl) \ + $(pkg-config --cflags --libs vorbis vorbisfile ogg) \ + -lopenal ./sdl_app \ No newline at end of file From b1954fd3346ab778fb4e9ec618a80eada3c3e076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 21:13:53 +0600 Subject: [PATCH 09/12] refacored some parts of main.cpp --- Environment.cpp | 4 + Environment.h | 8 +- Game.cpp | 200 +++++++++++++++++++++++++++++++++++++++++- Game.h | 12 ++- GameObjectManager.cpp | 173 +++++++++++++++++++++++++++++++++++- GameObjectManager.h | 10 +++ main.cpp | 9 +- 7 files changed, 405 insertions(+), 11 deletions(-) diff --git a/Environment.cpp b/Environment.cpp index 0bb9b23..31d6782 100644 --- a/Environment.cpp +++ b/Environment.cpp @@ -1,5 +1,7 @@ #include "Environment.h" +namespace ZL { + int Environment::windowHeaderHeight = 0; int Environment::width = 0; int Environment::height = 0; @@ -12,3 +14,5 @@ bool Environment::downPressed = false; Vector3f Environment::cameraShift = {0, 0, 0}; Vector3f Environment::characterPos = {0, 0, 0}; + +} // namespace ZL diff --git a/Environment.h b/Environment.h index f0dc366..30c554d 100644 --- a/Environment.h +++ b/Environment.h @@ -1,6 +1,8 @@ #pragma once #include "Math.h" +namespace ZL { + class Environment { public: static int windowHeaderHeight; @@ -13,6 +15,8 @@ public: static bool upPressed; static bool downPressed; - static ZL::Vector3f cameraShift; - static ZL::Vector3f characterPos; + static Vector3f cameraShift; + static Vector3f characterPos; }; + +} // namespace ZL diff --git a/Game.cpp b/Game.cpp index 4b1f617..655150d 100755 --- a/Game.cpp +++ b/Game.cpp @@ -1,8 +1,206 @@ #include "Game.h" #include "AnimatedModel.h" #include "BoneAnimatedModel.h" +#include "Utils.h" +#include "Inventory.h" // Add this include +#include +#include namespace ZL { -} \ No newline at end of file +void Game::worldToScreenCoordinates(Vector3f objectPos, + Matrix4f projectionModelView, + int screenWidth, int screenHeight, + int& screenX, int& screenY) { + + Vector4f inx = { objectPos.v[0], objectPos.v[1], objectPos.v[2], 1.0f}; + Vector4f clipCoords = MultMatrixVector(projectionModelView, inx); + + float ndcX = clipCoords.v[0] / clipCoords.v[3]; + float ndcY = clipCoords.v[1] / clipCoords.v[3]; + + screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth); + screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight); +} + +Game::Game() : window(nullptr), glContext(nullptr), exitGameLoop(false), + newTickCount(0), lastTickCount(0) { +} + +Game::~Game() { + if (glContext) { + SDL_GL_DeleteContext(glContext); + } + if (window) { + SDL_DestroyWindow(window); + } + SDL_Quit(); +} + +void Game::setup() { + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) { + SDL_Log("Failed to initialize SDL: %s", SDL_GetError()); + return; + } + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + + window = SDL_CreateWindow("Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + Environment::width, Environment::height, SDL_WINDOW_OPENGL); + + glContext = SDL_GL_CreateContext(window); + + ZL::BindOpenGlFunctions(); + ZL::CheckGlError(); + + // Initialize renderer + renderer.shaderManager.AddShaderFromFiles("default", "./default.vertex", "./default.fragment"); + renderer.shaderManager.AddShaderFromFiles("defaultColor", "./defaultColor.vertex", "./defaultColor.fragment"); + renderer.InitOpenGL(); + + // Initialize game objects + gameObjects.initialize(); +} + +void Game::drawScene() { + static const std::string defaultShaderName = "default"; + static const std::string vPositionName = "vPosition"; + static const std::string vTexCoordName = "vTexCoord"; + static const std::string textureUniformName = "Texture"; + + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + glViewport(0, 0, Environment::width, Environment::height); + + renderer.shaderManager.PushShader(defaultShaderName); + renderer.RenderUniform1i(textureUniformName, 0); + + renderer.EnableVertexAttribArray(vPositionName); + renderer.EnableVertexAttribArray(vTexCoordName); + + // 3D Scene rendering + { + renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, + static_cast(Environment::width) / static_cast(Environment::height), + 50, 10000); + renderer.PushMatrix(); + + renderer.LoadIdentity(); + renderer.TranslateMatrix({ 0,0, -100 * Environment::zoom }); + + float t = 0.3; + renderer.RotateMatrix(QuatFromRotateAroundX(t * M_PI / 2.0)); + + // Draw cone + glBindTexture(GL_TEXTURE_2D, gameObjects.coneTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(gameObjects.coneMeshMutable); + + renderer.TranslateMatrix(Environment::cameraShift); + + // Draw active objects + for (auto& ao : gameObjects.activeObjects) { + renderer.PushMatrix(); + renderer.TranslateMatrix(ao.objectPos); + glBindTexture(GL_TEXTURE_2D, ao.activeObjectTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(ao.activeObjectMeshMutable); + renderer.PopMatrix(); + } + + // Draw room + glBindTexture(GL_TEXTURE_2D, gameObjects.roomTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(gameObjects.textMeshMutable); + + auto latestProjectionModelView = renderer.GetProjectionModelViewMatrix(); + + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); + + // 2D UI rendering + renderer.PushProjectionMatrix(static_cast(Environment::width), + static_cast(Environment::height)); + renderer.PushMatrix(); + renderer.LoadIdentity(); + + // Draw highlighted objects UI + for (auto& ao : gameObjects.activeObjects) { + if (ao.highlighted) { + int screenX, screenY; + worldToScreenCoordinates(ao.objectPos, latestProjectionModelView, + Environment::width, Environment::height, screenX, screenY); + renderer.PushMatrix(); + renderer.TranslateMatrix(Vector3f{screenX + 0.f, screenY + 0.f, 0.0f}); + glBindTexture(GL_TEXTURE_2D, ao.activeObjectScreenTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(ao.activeObjectScreenMeshMutable); + renderer.PopMatrix(); + } + } + + // Draw inventory + const auto& inventory = ZL::ReturnInventory(); + for (size_t i = 0; i < inventory.size(); ++i) { + renderer.PushMatrix(); + float xPos = Environment::width - gameObjects.INVENTORY_MARGIN - gameObjects.INVENTORY_ICON_SIZE; + float yPos = gameObjects.INVENTORY_MARGIN + i * (gameObjects.INVENTORY_ICON_SIZE + gameObjects.INVENTORY_MARGIN); + renderer.TranslateMatrix(Vector3f{xPos, yPos, 0.0f}); + glBindTexture(GL_TEXTURE_2D, inventory[i].texture->getTexID()); + renderer.DrawVertexRenderStruct(gameObjects.inventoryIconMeshMutable); + renderer.PopMatrix(); + } + + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); + } + + renderer.DisableVertexAttribArray(vPositionName); + renderer.DisableVertexAttribArray(vTexCoordName); + renderer.shaderManager.PopShader(); + + CheckGlError(); +} + +void Game::processTickCount() { + if (lastTickCount == 0) { + lastTickCount = SDL_GetTicks64(); + return; + } + + newTickCount = SDL_GetTicks64(); + if (newTickCount - lastTickCount > CONST_TIMER_INTERVAL) { + size_t delta = (newTickCount - lastTickCount > CONST_MAX_TIME_INTERVAL) ? + CONST_MAX_TIME_INTERVAL : newTickCount - lastTickCount; + + gameObjects.update(); + + lastTickCount = newTickCount; + } +} + +void Game::render() { + SDL_GL_MakeCurrent(window, glContext); + ZL::CheckGlError(); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + drawScene(); + processTickCount(); + + SDL_GL_SwapWindow(window); +} + +void Game::update() { + SDL_Event event; + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + exitGameLoop = true; + } + gameObjects.handleEvent(event); + } + render(); +} + +} // namespace ZL \ No newline at end of file diff --git a/Game.h b/Game.h index 66c4804..73898d1 100755 --- a/Game.h +++ b/Game.h @@ -5,6 +5,8 @@ #include "Renderer.h" #include "Environment.h" +namespace ZL { + class Game { public: Game(); @@ -20,10 +22,14 @@ public: private: void processTickCount(); void drawScene(); + void worldToScreenCoordinates(Vector3f objectPos, + Matrix4f projectionModelView, + int screenWidth, int screenHeight, + int& screenX, int& screenY); SDL_Window* window; SDL_GLContext glContext; - ZL::Renderer renderer; + Renderer renderer; GameObjectManager gameObjects; bool exitGameLoop; @@ -32,4 +38,6 @@ private: static const size_t CONST_TIMER_INTERVAL = 10; static const size_t CONST_MAX_TIME_INTERVAL = 1000; -}; \ No newline at end of file +}; + +} // namespace ZL \ No newline at end of file diff --git a/GameObjectManager.cpp b/GameObjectManager.cpp index 5577188..87426b6 100644 --- a/GameObjectManager.cpp +++ b/GameObjectManager.cpp @@ -1,12 +1,181 @@ #include "GameObjectManager.h" +#include "Environment.h" +#include "ObjLoader.h" +#include "Inventory.h" +#include "TextModel.h" // Add this include for LoadFromTextFile + +namespace ZL { const float GameObjectManager::INVENTORY_ICON_SIZE = 32.0f; const float GameObjectManager::INVENTORY_MARGIN = 10.0f; void GameObjectManager::initialize() { - // Implementation coming from main.cpp setup() + // Load textures + roomTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./Kitchen_ceramics.bmp")); + coneTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./conus.bmp")); + + // Load models + colorCubeMesh = CreateCube3D(5.0); + colorCubeMeshMutable.data = CreateCube3D(5.0); + colorCubeMeshMutable.RefreshVBO(); + + testObjMesh = LoadFromObjFile("./chair_01.obj"); + testObjMesh.Scale(10); + testObjMesh.SwapZandY(); + testObjMeshMutable.data = testObjMesh; + testObjMeshMutable.RefreshVBO(); + + textMesh = ZL::LoadFromTextFile("./mesh001.txt"); // Add ZL:: namespace + coneMesh = ZL::LoadFromTextFile("./cone001.txt"); // Add ZL:: namespace + coneMesh.Scale(200); + + textMeshMutable.AssignFrom(textMesh); + textMeshMutable.RefreshVBO(); + coneMeshMutable.AssignFrom(coneMesh); + coneMeshMutable.RefreshVBO(); + + // Load bone animations + bx.LoadFromFile("mesh_armature_and_animation_data.txt"); + + // Create active object + ActiveObject ao1; + ao1.activeObjectMesh = ZL::LoadFromTextFile("./book001.txt"); // Add ZL:: namespace + ao1.activeObjectMesh.Scale(4); + ao1.activeObjectMeshMutable.AssignFrom(ao1.activeObjectMesh); + ao1.activeObjectMeshMutable.RefreshVBO(); + ao1.objectPos = Vector3f{50, 0, -300}; + ao1.activeObjectTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./book03.bmp")); + ao1.activeObjectScreenTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./aoscreen01.bmp")); + ao1.activeObjectScreenMesh = CreateRect2D({ 0.f, 0.f }, { 64.f, 64.f }, 0.5); + ao1.activeObjectScreenMeshMutable.AssignFrom(ao1.activeObjectScreenMesh); + ao1.activeObjectScreenMeshMutable.RefreshVBO(); + activeObjects.push_back(ao1); + + // Initialize audio + audioPlayer = std::make_unique(); + if (audioPlayer) { + audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); + } + + // Initialize inventory + inventoryIconMesh = CreateRect2D( + {0.0f, 0.0f}, + {INVENTORY_ICON_SIZE/2, INVENTORY_ICON_SIZE/2}, + 0.5f + ); + inventoryIconMeshMutable.AssignFrom(inventoryIconMesh); + inventoryIconMeshMutable.RefreshVBO(); + + // Add test items to inventory + auto testRoomTexture = std::make_shared(CreateTextureDataFromBmp24("./Kitchen_ceramics.bmp")); + auto testConeTexture = std::make_shared(CreateTextureDataFromBmp24("./conus.bmp")); + AddItemToInventory("RoomCeramics", testRoomTexture); + AddItemToInventory("Cone", testConeTexture); } void GameObjectManager::update() { - // Implementation coming from main.cpp update() + updateScene(16); // Добавим фиксированный timestep для обновления сцены } + +void GameObjectManager::handleEvent(const SDL_Event& event) { + if (event.type == SDL_MOUSEBUTTONDOWN) { + bx.Interpolate(animationCounter); + animationCounter += 2; + } + else if (event.type == SDL_MOUSEWHEEL) { + static const float zoomstep = 1.0f; + if (event.wheel.y > 0) { + Environment::zoom -= zoomstep; + } + else if (event.wheel.y < 0) { + Environment::zoom += zoomstep; + } + if (Environment::zoom < zoomstep) { + Environment::zoom = zoomstep; + } + } + else if (event.type == SDL_KEYDOWN) { + switch (event.key.keysym.sym) { + case SDLK_LEFT: + case SDLK_a: + Environment::leftPressed = true; + if (audioPlayer) { + audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } + break; + case SDLK_RIGHT: + case SDLK_d: + Environment::rightPressed = true; + if (audioPlayer) { + audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } + break; + case SDLK_UP: + case SDLK_w: + Environment::upPressed = true; + if (audioPlayer) { + audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } + break; + case SDLK_DOWN: + case SDLK_s: + Environment::downPressed = true; + if (audioPlayer) { + audioPlayer->playSound("Звук-Идут-по-земле.ogg"); + } + break; + // ...handle other keys... + } + } + else if (event.type == SDL_KEYUP) { + switch (event.key.keysym.sym) { + case SDLK_LEFT: + case SDLK_a: + Environment::leftPressed = false; + break; + case SDLK_RIGHT: + case SDLK_d: + Environment::rightPressed = false; + break; + case SDLK_UP: + case SDLK_w: + Environment::upPressed = false; + break; + case SDLK_DOWN: + case SDLK_s: + Environment::downPressed = false; + break; + } + } +} + +void GameObjectManager::updateScene(size_t ms) { + const float SPEED = 0.1f; + if (Environment::leftPressed) { + Environment::cameraShift.v[0] += SPEED * ms; + } + if (Environment::rightPressed) { + Environment::cameraShift.v[0] -= SPEED * ms; + } + if (Environment::upPressed) { + Environment::cameraShift.v[2] += SPEED * ms; + } + if (Environment::downPressed) { + Environment::cameraShift.v[2] -= SPEED * 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]; + + for (auto& ao : activeObjects) { + float dist = sqrtf( + pow(Environment::characterPos.v[0] - ao.objectPos.v[0], 2) + + pow(Environment::characterPos.v[1] - ao.objectPos.v[1], 2) + + pow(Environment::characterPos.v[2] - ao.objectPos.v[2], 2) + ); + ao.highlighted = (dist < 50.f); + } +} + +} // namespace ZL diff --git a/GameObjectManager.h b/GameObjectManager.h index 1e56e1f..e998d50 100644 --- a/GameObjectManager.h +++ b/GameObjectManager.h @@ -5,11 +5,16 @@ #include #include #include "ActiveObject.h" +#include + +namespace ZL { class GameObjectManager { public: void initialize(); void update(); + void handleEvent(const SDL_Event& event); + void updateScene(size_t ms); std::shared_ptr testObjTexturePtr; std::shared_ptr roomTexturePtr; @@ -38,4 +43,9 @@ public: static const float INVENTORY_ICON_SIZE; static const float INVENTORY_MARGIN; + +private: + int animationCounter = 0; }; + +} // namespace ZL diff --git a/main.cpp b/main.cpp index e13e50b..4aa257e 100755 --- a/main.cpp +++ b/main.cpp @@ -541,19 +541,20 @@ namespace ZL }; #include "Game.h" +#include "Environment.h" int main(int argc, char* argv[]) { constexpr int CONST_WIDTH = 1280; constexpr int CONST_HEIGHT = 720; - Environment::width = CONST_WIDTH; - Environment::height = CONST_HEIGHT; + ZL::Environment::width = CONST_WIDTH; + ZL::Environment::height = CONST_HEIGHT; - Game game; + ZL::Game game; game.setup(); #ifdef EMSCRIPTEN - emscripten_set_main_loop([]() { game.update(); }, 0, 1); + emscripten_set_main_loop([](){ game.update(); }, 0, 1); #else while (!game.shouldExit()) { game.update(); From 51a1cc742c2e8febfd41a776d564d5b7fdb7a7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 21:33:34 +0600 Subject: [PATCH 10/12] refacored some parts of main.cpp --- Game.cpp | 121 ++++-------------------------------------- Game.h | 11 ++-- RenderSystem.cpp | 133 +++++++++++++++++++++++++++++++++++++++++++++++ RenderSystem.h | 29 +++++++++++ start.sh | 2 +- 5 files changed, 177 insertions(+), 119 deletions(-) create mode 100644 RenderSystem.cpp create mode 100644 RenderSystem.h diff --git a/Game.cpp b/Game.cpp index 655150d..58d69ef 100755 --- a/Game.cpp +++ b/Game.cpp @@ -9,23 +9,14 @@ namespace ZL { -void Game::worldToScreenCoordinates(Vector3f objectPos, - Matrix4f projectionModelView, - int screenWidth, int screenHeight, - int& screenX, int& screenY) { - - Vector4f inx = { objectPos.v[0], objectPos.v[1], objectPos.v[2], 1.0f}; - Vector4f clipCoords = MultMatrixVector(projectionModelView, inx); - - float ndcX = clipCoords.v[0] / clipCoords.v[3]; - float ndcY = clipCoords.v[1] / clipCoords.v[3]; - - screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth); - screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight); -} - -Game::Game() : window(nullptr), glContext(nullptr), exitGameLoop(false), - newTickCount(0), lastTickCount(0) { +Game::Game() + : window(nullptr) + , glContext(nullptr) + , exitGameLoop(false) + , newTickCount(0) + , lastTickCount(0) + , renderer(renderSystem.getRenderer()) // Инициализация ссылки на renderer +{ } Game::~Game() { @@ -66,100 +57,8 @@ void Game::setup() { } void Game::drawScene() { - static const std::string defaultShaderName = "default"; - static const std::string vPositionName = "vPosition"; - static const std::string vTexCoordName = "vTexCoord"; - static const std::string textureUniformName = "Texture"; - - glClearColor(0.3f, 0.3f, 0.3f, 1.0f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, Environment::width, Environment::height); - - renderer.shaderManager.PushShader(defaultShaderName); - renderer.RenderUniform1i(textureUniformName, 0); - - renderer.EnableVertexAttribArray(vPositionName); - renderer.EnableVertexAttribArray(vTexCoordName); - - // 3D Scene rendering - { - renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, - static_cast(Environment::width) / static_cast(Environment::height), - 50, 10000); - renderer.PushMatrix(); - - renderer.LoadIdentity(); - renderer.TranslateMatrix({ 0,0, -100 * Environment::zoom }); - - float t = 0.3; - renderer.RotateMatrix(QuatFromRotateAroundX(t * M_PI / 2.0)); - - // Draw cone - glBindTexture(GL_TEXTURE_2D, gameObjects.coneTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(gameObjects.coneMeshMutable); - - renderer.TranslateMatrix(Environment::cameraShift); - - // Draw active objects - for (auto& ao : gameObjects.activeObjects) { - renderer.PushMatrix(); - renderer.TranslateMatrix(ao.objectPos); - glBindTexture(GL_TEXTURE_2D, ao.activeObjectTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(ao.activeObjectMeshMutable); - renderer.PopMatrix(); - } - - // Draw room - glBindTexture(GL_TEXTURE_2D, gameObjects.roomTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(gameObjects.textMeshMutable); - - auto latestProjectionModelView = renderer.GetProjectionModelViewMatrix(); - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - - // 2D UI rendering - renderer.PushProjectionMatrix(static_cast(Environment::width), - static_cast(Environment::height)); - renderer.PushMatrix(); - renderer.LoadIdentity(); - - // Draw highlighted objects UI - for (auto& ao : gameObjects.activeObjects) { - if (ao.highlighted) { - int screenX, screenY; - worldToScreenCoordinates(ao.objectPos, latestProjectionModelView, - Environment::width, Environment::height, screenX, screenY); - renderer.PushMatrix(); - renderer.TranslateMatrix(Vector3f{screenX + 0.f, screenY + 0.f, 0.0f}); - glBindTexture(GL_TEXTURE_2D, ao.activeObjectScreenTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(ao.activeObjectScreenMeshMutable); - renderer.PopMatrix(); - } - } - - // Draw inventory - const auto& inventory = ZL::ReturnInventory(); - for (size_t i = 0; i < inventory.size(); ++i) { - renderer.PushMatrix(); - float xPos = Environment::width - gameObjects.INVENTORY_MARGIN - gameObjects.INVENTORY_ICON_SIZE; - float yPos = gameObjects.INVENTORY_MARGIN + i * (gameObjects.INVENTORY_ICON_SIZE + gameObjects.INVENTORY_MARGIN); - renderer.TranslateMatrix(Vector3f{xPos, yPos, 0.0f}); - glBindTexture(GL_TEXTURE_2D, inventory[i].texture->getTexID()); - renderer.DrawVertexRenderStruct(gameObjects.inventoryIconMeshMutable); - renderer.PopMatrix(); - } - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - } - - renderer.DisableVertexAttribArray(vPositionName); - renderer.DisableVertexAttribArray(vTexCoordName); - renderer.shaderManager.PopShader(); - - CheckGlError(); + // Вместо прямого рисования используем RenderSystem + renderSystem.drawScene(gameObjects); } void Game::processTickCount() { diff --git a/Game.h b/Game.h index 73898d1..90f9567 100755 --- a/Game.h +++ b/Game.h @@ -2,7 +2,7 @@ #include #include "GameObjectManager.h" -#include "Renderer.h" +#include "RenderSystem.h" #include "Environment.h" namespace ZL { @@ -22,15 +22,12 @@ public: private: void processTickCount(); void drawScene(); - void worldToScreenCoordinates(Vector3f objectPos, - Matrix4f projectionModelView, - int screenWidth, int screenHeight, - int& screenX, int& screenY); SDL_Window* window; SDL_GLContext glContext; - Renderer renderer; + RenderSystem renderSystem; GameObjectManager gameObjects; + Renderer& renderer; // Ссылка на renderer из RenderSystem bool exitGameLoop; size_t newTickCount; @@ -40,4 +37,4 @@ private: static const size_t CONST_MAX_TIME_INTERVAL = 1000; }; -} // namespace ZL \ No newline at end of file +} // namespace ZL \ No newline at end of file diff --git a/RenderSystem.cpp b/RenderSystem.cpp new file mode 100644 index 0000000..8290d5b --- /dev/null +++ b/RenderSystem.cpp @@ -0,0 +1,133 @@ +#include "RenderSystem.h" +#include "Environment.h" +#include "Utils.h" +#include "Inventory.h" +#include + +namespace ZL { + +void RenderSystem::initialize() { + renderer.shaderManager.AddShaderFromFiles("default", "./default.vertex", "./default.fragment"); + renderer.shaderManager.AddShaderFromFiles("defaultColor", "./defaultColor.vertex", "./defaultColor.fragment"); + renderer.InitOpenGL(); +} + +void RenderSystem::drawScene(const GameObjectManager& gameObjects) { + static const std::string defaultShaderName = "default"; + static const std::string vPositionName = "vPosition"; + static const std::string vTexCoordName = "vTexCoord"; + static const std::string textureUniformName = "Texture"; + + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + + glViewport(0, 0, Environment::width, Environment::height); + + renderer.shaderManager.PushShader(defaultShaderName); + renderer.RenderUniform1i(textureUniformName, 0); + + renderer.EnableVertexAttribArray(vPositionName); + renderer.EnableVertexAttribArray(vTexCoordName); + + drawWorld(gameObjects); + drawUI(gameObjects); + + renderer.DisableVertexAttribArray(vPositionName); + renderer.DisableVertexAttribArray(vTexCoordName); + renderer.shaderManager.PopShader(); + + CheckGlError(); +} + +void RenderSystem::drawWorld(const GameObjectManager& gameObjects) { + renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, + static_cast(Environment::width) / static_cast(Environment::height), + 50, 10000); + renderer.PushMatrix(); + + renderer.LoadIdentity(); + renderer.TranslateMatrix({ 0,0, -100 * Environment::zoom }); + + float t = 0.3; + renderer.RotateMatrix(QuatFromRotateAroundX(t * M_PI / 2.0)); + + // Draw cone + glBindTexture(GL_TEXTURE_2D, gameObjects.coneTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(gameObjects.coneMeshMutable); + + renderer.TranslateMatrix(Environment::cameraShift); + + // Draw active objects + for (const auto& ao : gameObjects.activeObjects) { + renderer.PushMatrix(); + renderer.TranslateMatrix(ao.objectPos); + glBindTexture(GL_TEXTURE_2D, ao.activeObjectTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(ao.activeObjectMeshMutable); + renderer.PopMatrix(); + } + + // Draw room + glBindTexture(GL_TEXTURE_2D, gameObjects.roomTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(gameObjects.textMeshMutable); + + Matrix4f latestProjectionModelView = renderer.GetProjectionModelViewMatrix(); + + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); + + // Store matrix for UI rendering + currentProjectionModelView = latestProjectionModelView; +} + +void RenderSystem::drawUI(const GameObjectManager& gameObjects) { + renderer.PushProjectionMatrix(static_cast(Environment::width), + static_cast(Environment::height)); + renderer.PushMatrix(); + renderer.LoadIdentity(); + + // Draw highlighted objects UI + for (const auto& ao : gameObjects.activeObjects) { + if (ao.highlighted) { + int screenX, screenY; + worldToScreenCoordinates(ao.objectPos, currentProjectionModelView, + Environment::width, Environment::height, screenX, screenY); + renderer.PushMatrix(); + renderer.TranslateMatrix(Vector3f{screenX + 0.f, screenY + 0.f, 0.0f}); + glBindTexture(GL_TEXTURE_2D, ao.activeObjectScreenTexturePtr->getTexID()); + renderer.DrawVertexRenderStruct(ao.activeObjectScreenMeshMutable); + renderer.PopMatrix(); + } + } + + // Draw inventory + const auto& inventory = ZL::ReturnInventory(); + for (size_t i = 0; i < inventory.size(); ++i) { + renderer.PushMatrix(); + float xPos = Environment::width - gameObjects.INVENTORY_MARGIN - gameObjects.INVENTORY_ICON_SIZE; + float yPos = gameObjects.INVENTORY_MARGIN + i * (gameObjects.INVENTORY_ICON_SIZE + gameObjects.INVENTORY_MARGIN); + renderer.TranslateMatrix(Vector3f{xPos, yPos, 0.0f}); + glBindTexture(GL_TEXTURE_2D, inventory[i].texture->getTexID()); + renderer.DrawVertexRenderStruct(gameObjects.inventoryIconMeshMutable); + renderer.PopMatrix(); + } + + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); +} + +void RenderSystem::worldToScreenCoordinates(Vector3f objectPos, + Matrix4f projectionModelView, + int screenWidth, int screenHeight, + int& screenX, int& screenY) { + + Vector4f inx = { objectPos.v[0], objectPos.v[1], objectPos.v[2], 1.0f}; + Vector4f clipCoords = MultMatrixVector(projectionModelView, inx); + + float ndcX = clipCoords.v[0] / clipCoords.v[3]; + float ndcY = clipCoords.v[1] / clipCoords.v[3]; + + screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth); + screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight); +} + +} // namespace ZL diff --git a/RenderSystem.h b/RenderSystem.h new file mode 100644 index 0000000..951bcbd --- /dev/null +++ b/RenderSystem.h @@ -0,0 +1,29 @@ +#pragma once +#include "Renderer.h" +#include "GameObjectManager.h" +#include + +namespace ZL { + +class RenderSystem { +public: + RenderSystem() = default; + void initialize(); + void drawScene(const GameObjectManager& gameObjects); + Renderer& getRenderer() { return renderer; } + + void worldToScreenCoordinates(Vector3f objectPos, + Matrix4f projectionModelView, + int screenWidth, int screenHeight, + int& screenX, int& screenY); + +private: + void drawWorld(const GameObjectManager& gameObjects); + void drawUI(const GameObjectManager& gameObjects); + + Renderer renderer; + ShaderManager shaderManager; + Matrix4f currentProjectionModelView; // Добавлено для хранения матрицы между drawWorld и drawUI +}; + +} // namespace ZL diff --git a/start.sh b/start.sh index 65dd930..b3235c2 100755 --- a/start.sh +++ b/start.sh @@ -1,7 +1,7 @@ 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 \ + Inventory.cpp Environment.cpp GameObjectManager.cpp RenderSystem.cpp \ -o sdl_app -O2 -std=c++17 \ -I cmakeaudioplayer/include \ $(pkg-config --cflags --libs sdl2 gl) \ From 55133bbd877959dc1bcfb902f6d78e4b6d1d95e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 21:43:31 +0600 Subject: [PATCH 11/12] fully refactored main.cpp --- main.cpp | 542 ------------------------------------------------------- 1 file changed, 542 deletions(-) diff --git a/main.cpp b/main.cpp index 4aa257e..d20823f 100755 --- a/main.cpp +++ b/main.cpp @@ -1,545 +1,3 @@ -#include "TextureManager.h" -#include "ShaderManager.h" -#include "Renderer.h" -#include "ObjLoader.h" - -#include "Physics.h" -#include - - -#include -#include -#include -#include - -#include "Game.h" -#include "AnimatedModel.h" -#include "BoneAnimatedModel.h" -#include "TextModel.h" - -#include "Inventory.h" -#include "cmakeaudioplayer/include/AudioPlayer.hpp" -#include - -namespace ZL -{ - void worldToScreenCoordinates(Vector3f objectPos, - Matrix4f projectionModelView, - int screenWidth, int screenHeight, - int& screenX, int& screenY) { - - - Vector4f inx = { objectPos.v[0], objectPos.v[1], objectPos.v[2], 1.0f}; - - Vector4f clipCoords = MultMatrixVector(projectionModelView, inx); - - // ������������� ������� - float ndcX = clipCoords.v[0] / clipCoords.v[3]; - float ndcY = clipCoords.v[1] / clipCoords.v[3]; - - // ����������� NDC � �������� ���������� - screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth); - //screenY = (int)((1.0f - ndcY) * 0.5f * screenHeight); - screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight); - } - - namespace Env - { - int windowHeaderHeight = 0; - - int width = 0; - int height = 0; - - float zoom = 10.0; - - bool leftPressed = false; - bool rightPressed = false; - bool upPressed = false; - bool downPressed = false; - - Vector3f cameraShift = {0,0,0}; - Vector3f characterPos = { 0,0,0 }; - - /* - Vector2f birdStartPos; - - float backgroundSectionWidth; - - int getActualClientHeight() - { - return height - windowHeaderHeight; - }*/ - } - - struct ActiveObject - { - std::shared_ptr activeObjectTexturePtr; - VertexDataStruct activeObjectMesh; - VertexRenderStruct activeObjectMeshMutable; - - std::shared_ptr activeObjectScreenTexturePtr; - VertexDataStruct activeObjectScreenMesh; - VertexRenderStruct activeObjectScreenMeshMutable; - - - Vector3f objectPos; - bool highlighted = false; - }; - - namespace GameObjects - { - std::shared_ptr testObjTexturePtr; - std::shared_ptr roomTexturePtr; - std::shared_ptr coneTexturePtr; - //std::shared_ptr activeObjectTexturePtr; - - VertexDataStruct colorCubeMesh; - VertexRenderStruct colorCubeMeshMutable; - - VertexDataStruct testObjMesh; - VertexRenderStruct testObjMeshMutable; - - BoneSystem bx; - VertexRenderStruct bxMutable; - - VertexDataStruct textMesh; - VertexRenderStruct textMeshMutable; - - VertexDataStruct coneMesh; - VertexRenderStruct coneMeshMutable; - - std::vector activeObjects; - - // Add AudioPlayer instance - std::unique_ptr audioPlayer; - - // Добавляем структуры для иконок инвентаря - VertexDataStruct inventoryIconMesh; - VertexRenderStruct inventoryIconMeshMutable; - const float INVENTORY_ICON_SIZE = 32.0f; // Размер иконки в пикселях - const float INVENTORY_MARGIN = 10.0f; // Отступ от края экрана - } - - static SDL_Window* window = NULL; - static SDL_GLContext gl_context; - - Renderer renderer; - - //GameState gs; - - - const size_t CONST_TIMER_INTERVAL = 10; - - const size_t CONST_MAX_TIME_INTERVAL = 1000; - - bool ExitGameLoop = false; - - //To calculate when to call Update - size_t NewTickCount; - size_t LastTickCount; - - - void DrawScene() - { - static const std::string defaultShaderName = "default"; - static const std::string colorShaderName = "defaultColor"; - - static const std::string vPositionName = "vPosition"; - static const std::string vTexCoordName = "vTexCoord"; - static const std::string vColorName = "vColor"; - static const std::string textureUniformName = "Texture"; - - glClearColor(0.3f, 0.3f, 0.3f, 1.0f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - - glViewport(0, 0, Env::width, Env::height); - - renderer.shaderManager.PushShader(defaultShaderName); - renderer.RenderUniform1i(textureUniformName, 0); - - renderer.EnableVertexAttribArray(vPositionName); - renderer.EnableVertexAttribArray(vTexCoordName); - - renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, static_cast(Env::width) / static_cast(Env::height), 50, 10000); - renderer.PushMatrix(); - - renderer.LoadIdentity(); - - renderer.TranslateMatrix({ 0,0, -100* Env::zoom }); - - float t = 0.3; - - renderer.RotateMatrix(QuatFromRotateAroundX(t * M_PI / 2.0)); - - //GameObjects::textMeshMutable.AssignFrom(GameObjects::textMesh); - //GameObjects::textMeshMutable.RefreshVBO(); - - glBindTexture(GL_TEXTURE_2D, GameObjects::coneTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(GameObjects::coneMeshMutable); - - renderer.TranslateMatrix(Env::cameraShift); - - - //ActiveObject ao1; - - for (auto& ao : GameObjects::activeObjects) - { - renderer.PushMatrix(); - renderer.TranslateMatrix(ao.objectPos); - glBindTexture(GL_TEXTURE_2D, ao.activeObjectTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(ao.activeObjectMeshMutable); - renderer.PopMatrix(); - } - - glBindTexture(GL_TEXTURE_2D, GameObjects::roomTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(GameObjects::textMeshMutable); - - auto latestProjectionModelView = renderer.GetProjectionModelViewMatrix(); - - renderer.PopMatrix(); - - renderer.PopProjectionMatrix(); - glClear(GL_DEPTH_BUFFER_BIT); - renderer.PushProjectionMatrix(static_cast(Env::width), static_cast(Env::height)); - renderer.PushMatrix(); - - renderer.LoadIdentity(); - - for (auto& ao : GameObjects::activeObjects) - { - if (ao.highlighted) - { - int screenX, screenY; - worldToScreenCoordinates(ao.objectPos, latestProjectionModelView, Env::width, Env::height, screenX, screenY); - renderer.PushMatrix(); - renderer.TranslateMatrix(Vector3f{screenX + 0.f, screenY + 0.f, 0.0f}); - glBindTexture(GL_TEXTURE_2D, ao.activeObjectScreenTexturePtr->getTexID()); - renderer.DrawVertexRenderStruct(ao.activeObjectScreenMeshMutable); - renderer.PopMatrix(); - } - } - - // Отрисовка иконок инвентаря - const auto& inventory = ReturnInventory(); - for (size_t i = 0; i < inventory.size(); ++i) { - renderer.PushMatrix(); - float xPos = Env::width - GameObjects::INVENTORY_MARGIN - GameObjects::INVENTORY_ICON_SIZE; - float yPos = GameObjects::INVENTORY_MARGIN + i * (GameObjects::INVENTORY_ICON_SIZE + GameObjects::INVENTORY_MARGIN); - renderer.TranslateMatrix(Vector3f{xPos, yPos, 0.0f}); - glBindTexture(GL_TEXTURE_2D, inventory[i].texture->getTexID()); - renderer.DrawVertexRenderStruct(GameObjects::inventoryIconMeshMutable); - renderer.PopMatrix(); - } - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - - renderer.DisableVertexAttribArray(vPositionName); - renderer.DisableVertexAttribArray(vTexCoordName); - - renderer.shaderManager.PopShader(); - - CheckGlError(); - - } - - - void UpdateScene(size_t ms) - { - const float SPEED = 0.1f; - if (Env::leftPressed) - { - Env::cameraShift.v[0] += SPEED * ms; - } - if (Env::rightPressed) - { - Env::cameraShift.v[0] -= SPEED * ms; - } - - if (Env::upPressed) - { - Env::cameraShift.v[2] += SPEED * ms; - } - if (Env::downPressed) - { - Env::cameraShift.v[2] -= SPEED * ms; - } - - Env::characterPos.v[0] = -Env::cameraShift.v[0]; - Env::characterPos.v[1] = -Env::cameraShift.v[1]; - Env::characterPos.v[2] = -Env::cameraShift.v[2]; - - for (auto& ao : GameObjects::activeObjects) - { - if (sqrtf( - (Env::characterPos.v[0] - ao.objectPos.v[0]) * (Env::characterPos.v[0] - ao.objectPos.v[0]) - + - (Env::characterPos.v[1] - ao.objectPos.v[1]) * (Env::characterPos.v[1] - ao.objectPos.v[1]) - + - (Env::characterPos.v[2] - ao.objectPos.v[2]) * (Env::characterPos.v[2] - ao.objectPos.v[2]) - ) < 50.f) - { - ao.highlighted = true; - } - else - { - ao.highlighted = false; - } - } - - } - - void ProcessTickCount() - { - - if (LastTickCount == 0) - { - LastTickCount = SDL_GetTicks64(); - return; - } - - NewTickCount = SDL_GetTicks64(); - if (NewTickCount - LastTickCount > CONST_TIMER_INTERVAL) - { - if (NewTickCount - LastTickCount > CONST_MAX_TIME_INTERVAL) - { - UpdateScene(CONST_MAX_TIME_INTERVAL); //Limit game update speed to FPS - } - else - { - UpdateScene(NewTickCount - LastTickCount); - } - - LastTickCount = NewTickCount; - } - - } - - void setup() { - static const int BIRD_WIDTH = 512; - static const int BIRD_HEIGHT = 512; - - static const int BACKGROUND_WIDTH = 900; - static const int BACKGROUND_HEIGHT = 504; - - static const int PIPE_WIDTH = 244; - static const int PIPE_HEIGHT = 1500; - - static const int GAMEOVER_WIDTH = 1400; - static const int GAMEOVER_HEIGHT = 720; - - ZL::BindOpenGlFunctions(); - - CheckGlError(); - - //Load shaders: - std::cout << "Hello test 1" << std::endl; - renderer.shaderManager.AddShaderFromFiles("default", "./default.vertex", "./default.fragment"); - - std::cout << "Hello test 2" << std::endl; - renderer.shaderManager.AddShaderFromFiles("defaultColor", "./defaultColor.vertex", "./defaultColor.fragment"); - std::cout << "Hello test 2x" << std::endl; - - GameObjects::bx.LoadFromFile("mesh_armature_and_animation_data.txt"); - - std::cout << "Hello test 3" << std::endl; - - CheckGlError(); - - GameObjects::roomTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./Kitchen_ceramics.bmp")); - GameObjects::coneTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./conus.bmp")); - - GameObjects::colorCubeMesh = CreateCube3D(5.0); - GameObjects::colorCubeMeshMutable.data = CreateCube3D(5.0); - GameObjects::colorCubeMeshMutable.RefreshVBO(); - - GameObjects::testObjMesh = LoadFromObjFile("./chair_01.obj"); - GameObjects::testObjMesh.Scale(10); - GameObjects::testObjMesh.SwapZandY(); - GameObjects::testObjMeshMutable.data = GameObjects::testObjMesh; - GameObjects::testObjMeshMutable.RefreshVBO(); - - GameObjects::textMesh = LoadFromTextFile("./mesh001.txt"); - - GameObjects::coneMesh = LoadFromTextFile("./cone001.txt"); - - GameObjects::coneMesh.Scale(200); - - GameObjects::textMeshMutable.AssignFrom(GameObjects::textMesh); - GameObjects::textMeshMutable.RefreshVBO(); - GameObjects::coneMeshMutable.AssignFrom(GameObjects::coneMesh); - GameObjects::coneMeshMutable.RefreshVBO(); - - - ActiveObject ao1; - - - - ao1.activeObjectMesh = LoadFromTextFile("./book001.txt"); - ao1.activeObjectMesh.Scale(4); - - ao1.activeObjectMeshMutable.AssignFrom(ao1.activeObjectMesh); - ao1.activeObjectMeshMutable.RefreshVBO(); - - ao1.objectPos = Vector3f{50, 0, -300}; - ao1.activeObjectTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./book03.bmp")); - - ao1.activeObjectScreenTexturePtr = std::make_shared(CreateTextureDataFromBmp24("./aoscreen01.bmp")); - - ao1.activeObjectScreenMesh = CreateRect2D({ 0.f, 0.f }, { 64.f, 64.f }, 0.5); - ao1.activeObjectScreenMeshMutable.AssignFrom(ao1.activeObjectScreenMesh); - ao1.activeObjectScreenMeshMutable.RefreshVBO(); - - GameObjects::activeObjects.push_back(ao1); - - - - std::cout << "Hello test 4x" << std::endl; - - renderer.InitOpenGL(); - - CheckGlError(); - - - std::cout << "Hello test 5x" << std::endl; - -// ТЕСТИРУЕМ ВЗАИМОДЕЙСТВИЕ С ИНВЕНТАРЕМ - auto roomTexturePtr = std::make_shared(ZL::CreateTextureDataFromBmp24("./Kitchen_ceramics.bmp")); - auto coneTexturePtr = std::make_shared(ZL::CreateTextureDataFromBmp24("./conus.bmp")); - - // Добавляем предметы в инвентарь - ZL::AddItemToInventory("RoomCeramics", roomTexturePtr); - ZL::AddItemToInventory("Cone", coneTexturePtr); - - ZL::PrintInventory(); - - // Initialize audio player and start background music - GameObjects::audioPlayer = std::make_unique(); - if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); - } - - // Инициализация меша иконки инвентаря - GameObjects::inventoryIconMesh = CreateRect2D( - {0.0f, 0.0f}, - {GameObjects::INVENTORY_ICON_SIZE/2, GameObjects::INVENTORY_ICON_SIZE/2}, - 0.5f - ); - GameObjects::inventoryIconMeshMutable.AssignFrom(GameObjects::inventoryIconMesh); - GameObjects::inventoryIconMeshMutable.RefreshVBO(); - - /// - } - - void render() { - - SDL_GL_MakeCurrent(window, gl_context); - - CheckGlError(); - - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - DrawScene(); - ProcessTickCount(); - - SDL_GL_SwapWindow(window); - - } - - void update() { - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - ExitGameLoop = true; - } - if (event.type == SDL_MOUSEBUTTONDOWN) { - static int x = 0; - - GameObjects::bx.Interpolate(x); - x = x + 2; - } - if (event.type == SDL_MOUSEWHEEL) { - - static const float zoomstep = 1.0f; - if (event.wheel.y > 0) { - // ��������� ����� - ����������� zoom - Env::zoom -= zoomstep; - } - else if (event.wheel.y < 0) { - // ��������� ���� - ��������� zoom - Env::zoom += zoomstep; - } - // ������������ zoom, ����� �� �� ���� ������������� - if (Env::zoom < zoomstep) { - Env::zoom = zoomstep; - } - } - if (event.type == SDL_KEYDOWN) { - switch (event.key.keysym.sym) { - case SDLK_LEFT: - case SDLK_a: - Env::leftPressed = true; - if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } - break; - case SDLK_RIGHT: - case SDLK_d: - Env::rightPressed = true; - if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } - break; - case SDLK_UP: - case SDLK_w: - Env::upPressed = true; - if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } - break; - case SDLK_DOWN: - case SDLK_s: - Env::downPressed = true; - if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playSound("Звук-Идут-по-земле.ogg"); - } - break; - case SDLK_SPACE: - if (GameObjects::audioPlayer) { - GameObjects::audioPlayer->playMusic("Symphony No.6 (1st movement).ogg"); - } - break; - } - } - - if (event.type == SDL_KEYUP) { - switch (event.key.keysym.sym) { - case SDLK_LEFT: - case SDLK_a: - Env::leftPressed = false; - break; - case SDLK_RIGHT: - case SDLK_d: - Env::rightPressed = false; - break; - case SDLK_UP: - case SDLK_w: - Env::upPressed = false; - break; - case SDLK_DOWN: - case SDLK_s: - Env::downPressed = false; - break; - } - } - } - - render(); - } - -}; - #include "Game.h" #include "Environment.h" From 2d0c7ec166c660fe924387fdb916970bc272ee34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D1=8C=D0=B1=D0=B5=D1=80=D1=82=20=D0=93=D0=B0?= =?UTF-8?q?=D0=B4=D0=B8=D0=B5=D0=B2?= Date: Sat, 1 Mar 2025 22:14:33 +0600 Subject: [PATCH 12/12] added mouse handling --- GameObjectManager.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++ GameObjectManager.h | 8 ++++++++ RenderSystem.cpp | 4 ++++ RenderSystem.h | 2 ++ 4 files changed, 61 insertions(+) diff --git a/GameObjectManager.cpp b/GameObjectManager.cpp index 87426b6..d669ab5 100644 --- a/GameObjectManager.cpp +++ b/GameObjectManager.cpp @@ -147,6 +147,11 @@ void GameObjectManager::handleEvent(const SDL_Event& event) { break; } } + if (event.type == SDL_MOUSEMOTION) { + // Сохраняем позицию мыши для последующей проверки + lastMouseX = event.motion.x; + lastMouseY = event.motion.y; + } } void GameObjectManager::updateScene(size_t ms) { @@ -178,4 +183,46 @@ void GameObjectManager::updateScene(size_t ms) { } } +bool GameObjectManager::isPointInObject(int screenX, int screenY, int objectScreenX, int objectScreenY) const { + // Простая проверка попадания точки в квадрат 64x64 вокруг центра объекта + const int objectSize = 32; // Половина размера области выделения + return (screenX >= objectScreenX - objectSize && + screenX <= objectScreenX + objectSize && + screenY >= objectScreenY - objectSize && + screenY <= objectScreenY + objectSize); +} + +void GameObjectManager::checkMouseIntersection(int mouseX, int mouseY, const Matrix4f& projectionModelView) { + for (auto& ao : activeObjects) { + int screenX, screenY; + worldToScreenCoordinates(ao.objectPos, projectionModelView, + Environment::width, Environment::height, screenX, screenY); + + if (isPointInObject(mouseX, mouseY, screenX, screenY)) { + std::cout << "Mouse over object at screen coordinates: " + << screenX << ", " << screenY + << " (world pos: " + << ao.objectPos.v[0] << ", " + << ao.objectPos.v[1] << ", " + << ao.objectPos.v[2] << ")" + << std::endl; + } + } +} + +void GameObjectManager::worldToScreenCoordinates(Vector3f objectPos, + Matrix4f projectionModelView, + int screenWidth, int screenHeight, + int& screenX, int& screenY) { + + Vector4f inx = { objectPos.v[0], objectPos.v[1], objectPos.v[2], 1.0f}; + Vector4f clipCoords = MultMatrixVector(projectionModelView, inx); + + float ndcX = clipCoords.v[0] / clipCoords.v[3]; + float ndcY = clipCoords.v[1] / clipCoords.v[3]; + + screenX = (int)((ndcX + 1.0f) * 0.5f * screenWidth); + screenY = (int)((1.0f + ndcY) * 0.5f * screenHeight); +} + } // namespace ZL diff --git a/GameObjectManager.h b/GameObjectManager.h index e998d50..8f32892 100644 --- a/GameObjectManager.h +++ b/GameObjectManager.h @@ -15,6 +15,7 @@ public: void update(); void handleEvent(const SDL_Event& event); void updateScene(size_t ms); + void checkMouseIntersection(int mouseX, int mouseY, const Matrix4f& projectionModelView); // Добавляем новый метод std::shared_ptr testObjTexturePtr; std::shared_ptr roomTexturePtr; @@ -46,6 +47,13 @@ public: private: int animationCounter = 0; + int lastMouseX = 0; // Добавляем переменные для хранения позиции мыши + int lastMouseY = 0; + bool isPointInObject(int screenX, int screenY, int objectScreenX, int objectScreenY) const; + void worldToScreenCoordinates(Vector3f objectPos, // Добавляем метод + Matrix4f projectionModelView, + int screenWidth, int screenHeight, + int& screenX, int& screenY); }; } // namespace ZL diff --git a/RenderSystem.cpp b/RenderSystem.cpp index 8290d5b..aa5c38e 100644 --- a/RenderSystem.cpp +++ b/RenderSystem.cpp @@ -71,6 +71,10 @@ void RenderSystem::drawWorld(const GameObjectManager& gameObjects) { renderer.DrawVertexRenderStruct(gameObjects.textMeshMutable); Matrix4f latestProjectionModelView = renderer.GetProjectionModelViewMatrix(); + + // Проверяем пересечение с мышью после расчета всех матриц + const_cast(gameObjects).checkMouseIntersection( + lastMouseX, lastMouseY, latestProjectionModelView); renderer.PopMatrix(); renderer.PopProjectionMatrix(); diff --git a/RenderSystem.h b/RenderSystem.h index 951bcbd..26d12b7 100644 --- a/RenderSystem.h +++ b/RenderSystem.h @@ -24,6 +24,8 @@ private: Renderer renderer; ShaderManager shaderManager; Matrix4f currentProjectionModelView; // Добавлено для хранения матрицы между drawWorld и drawUI + int lastMouseX = 0; + int lastMouseY = 0; }; } // namespace ZL