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..31d6782 --- /dev/null +++ b/Environment.cpp @@ -0,0 +1,18 @@ +#include "Environment.h" + +namespace ZL { + +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}; + +} // namespace ZL diff --git a/Environment.h b/Environment.h new file mode 100644 index 0000000..30c554d --- /dev/null +++ b/Environment.h @@ -0,0 +1,22 @@ +#pragma once +#include "Math.h" + +namespace ZL { + +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 Vector3f cameraShift; + static Vector3f characterPos; +}; + +} // namespace ZL diff --git a/Game.cpp b/Game.cpp index 4b1f617..041c699 100755 --- a/Game.cpp +++ b/Game.cpp @@ -1,8 +1,105 @@ #include "Game.h" #include "AnimatedModel.h" #include "BoneAnimatedModel.h" +#include "Utils.h" +#include "Inventory.h" // Add this include +#include "OpenGlExtensions.h" +#include namespace ZL { -} \ No newline at end of file +Game::Game() + : window(nullptr) + , glContext(nullptr) + , exitGameLoop(false) + , newTickCount(0) + , lastTickCount(0) + , renderer(renderSystem.getRenderer()) // Инициализация ссылки на renderer +{ +} + +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() { + // Вместо прямого рисования используем RenderSystem + renderSystem.drawScene(gameObjects); +} + +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 a76b369..2c803cd 100755 --- a/Game.h +++ b/Game.h @@ -1,14 +1,40 @@ #pragma once -#include "Math.h" -#include "Physics.h" -#include "TextureManager.h" -#include "Renderer.h" -#include "AnimatedModel.h" -#include "BoneAnimatedModel.h" -#include +#include "OpenGlExtensions.h" +#include "GameObjectManager.h" +#include "RenderSystem.h" +#include "Environment.h" -namespace ZL -{ +namespace ZL { -} \ No newline at end of file +class Game { +public: + Game(); + ~Game(); + + void setup(); + void run(); + void update(); + void render(); + + bool shouldExit() const { return exitGameLoop; } + +private: + void processTickCount(); + void drawScene(); + + SDL_Window* window; + SDL_GLContext glContext; + RenderSystem renderSystem; + GameObjectManager gameObjects; + Renderer& renderer; // Ссылка на renderer из RenderSystem + + 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; +}; + +} // namespace ZL \ No newline at end of file diff --git a/GameObjectManager.cpp b/GameObjectManager.cpp new file mode 100644 index 0000000..d669ab5 --- /dev/null +++ b/GameObjectManager.cpp @@ -0,0 +1,228 @@ +#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() { + // 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() { + 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; + } + } + if (event.type == SDL_MOUSEMOTION) { + // Сохраняем позицию мыши для последующей проверки + lastMouseX = event.motion.x; + lastMouseY = event.motion.y; + } +} + +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); + } +} + +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 new file mode 100644 index 0000000..1b8eab2 --- /dev/null +++ b/GameObjectManager.h @@ -0,0 +1,59 @@ +#pragma once +#include "TextureManager.h" +#include "BoneAnimatedModel.h" +#include "cmakeaudioplayer/include/AudioPlayer.hpp" +#include +#include +#include "ActiveObject.h" +#include "OpenGlExtensions.h" + +namespace ZL { + +class GameObjectManager { +public: + void initialize(); + 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; + 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; + +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/GameWorld.cpp b/GameWorld.cpp new file mode 100644 index 0000000..352154d --- /dev/null +++ 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 new file mode 100644 index 0000000..2839dfd --- /dev/null +++ b/GameWorld.h @@ -0,0 +1,18 @@ +#pragma once +#include "Math.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 new file mode 100644 index 0000000..0addbde --- /dev/null +++ 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 new file mode 100644 index 0000000..9ec898f --- /dev/null +++ b/InputManager.h @@ -0,0 +1,17 @@ +#pragma once +#include "OpenGlExtensions.h" + +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/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/RenderSystem.cpp b/RenderSystem.cpp new file mode 100644 index 0000000..aa5c38e --- /dev/null +++ b/RenderSystem.cpp @@ -0,0 +1,137 @@ +#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(); + + // Проверяем пересечение с мышью после расчета всех матриц + const_cast(gameObjects).checkMouseIntersection( + lastMouseX, lastMouseY, latestProjectionModelView); + + 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..26d12b7 --- /dev/null +++ b/RenderSystem.h @@ -0,0 +1,31 @@ +#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 + int lastMouseX = 0; + int lastMouseY = 0; +}; + +} // namespace ZL diff --git a/ZeptoLabTest1.vcxproj b/ZeptoLabTest1.vcxproj index 91bbfb3..c086b41 100755 --- a/ZeptoLabTest1.vcxproj +++ b/ZeptoLabTest1.vcxproj @@ -116,13 +116,13 @@ true _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true - C:\Work\SDL2-2.28.3\include;C:\Work\Projects\lpng1645\build\install\include + C:\Work\SDL2-2.28.3\include;C:\Work\Projects\lpng1645\build\install\include;C:\Work\OpenAL 1.1 SDK\include;C:\Work\Projects\libogg\include;C:\Work\Projects\vorbis\include Console true - libpng16_staticd.lib;SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;shell32.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) - C:\Work\SDL2-2.28.3\lib\x64;C:\Work\Projects\lpng1645\build\install\lib + libogg_static.lib;audioplayer.lib;vorbisfile.lib;vorbis.lib;OpenAL32.lib;libpng16_staticd.lib;SDL2.lib;SDL2main.lib;opengl32.lib;glu32.lib;shell32.lib;opengl32.lib;glu32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib + C:\Work\Projects\ZeptoLabTest1\cmakeaudioplayer\build\Debug;C:\Work\SDL2-2.28.3\lib\x64;C:\Work\Projects\lpng1645\build\install\lib;C:\Work\Projects\vorbis\build\lib\Debug;C:\Work\OpenAL 1.1 SDK\libs\Win64;C:\Work\Projects\libogg\win32\VS2010\x64\Debug @@ -146,7 +146,11 @@ + + + + @@ -155,15 +159,21 @@ + + + + + + @@ -171,6 +181,7 @@ + diff --git a/ZeptoLabTest1.vcxproj.filters b/ZeptoLabTest1.vcxproj.filters index 49bb6e2..14f9358 100755 --- a/ZeptoLabTest1.vcxproj.filters +++ b/ZeptoLabTest1.vcxproj.filters @@ -57,6 +57,21 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -101,5 +116,23 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ 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/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 b31d295..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); @@ -44,28 +51,35 @@ 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); } -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); @@ -101,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 bf98cdb..d20823f 100755 --- a/main.cpp +++ b/main.cpp @@ -1,579 +1,24 @@ -#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 "Environment.h" -#include "Inventory.h" -#include +int main(int argc, char* argv[]) { + constexpr int CONST_WIDTH = 1280; + constexpr int CONST_HEIGHT = 720; -namespace ZL -{ - void worldToScreenCoordinates(Vector3f objectPos, - Matrix4f projectionModelView, - int screenWidth, int screenHeight, - int& screenX, int& screenY) { + ZL::Environment::width = CONST_WIDTH; + ZL::Environment::height = CONST_HEIGHT; - - 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; - } - - 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(colorShaderName); - renderer.RenderUniform1i(textureUniformName, 0); - renderer.EnableVertexAttribArray(vPositionName); - - 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::bxMutable.AssignFrom(GameObjects::bx.mesh); - GameObjects::bxMutable.RefreshVBO(); - renderer.DrawVertexRenderStruct(GameObjects::bxMutable); - - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - - renderer.DisableVertexAttribArray(vPositionName); - - renderer.shaderManager.PopShader(); -#if 0 - - 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(); - } - } - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - - renderer.DisableVertexAttribArray(vPositionName); - renderer.DisableVertexAttribArray(vTexCoordName); - - renderer.shaderManager.PopShader(); - -#endif - 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"); - GameObjects::bx.LoadFromFile("via004.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); - - std::cout << "Before removal:\n"; - ZL::PrintInventory(); - - // Удаляем "Cone" из инвентаря - ZL::RemoveItemFromInventory("Cone"); - - std::cout << "\nAfter removal:\n"; - ZL::PrintInventory(); - } - - 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 + 3; - } - 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; - break; - case SDLK_RIGHT: - case SDLK_d: - Env::rightPressed = true; - break; - case SDLK_UP: - case SDLK_w: - Env::upPressed = true; - break; - case SDLK_DOWN: - case SDLK_s: - Env::downPressed = true; - 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(); - } - -}; - -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; + ZL::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/sounds/Звук-Идут-по-земле.ogg b/sounds/Звук-Идут-по-земле.ogg new file mode 100644 index 0000000..fca9763 Binary files /dev/null and b/sounds/Звук-Идут-по-земле.ogg differ diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..b3235c2 --- /dev/null +++ b/start.sh @@ -0,0 +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 Environment.cpp GameObjectManager.cpp RenderSystem.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