From b1fab5bc562f8597a1329c5b5f2a338b7c1ee191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihai=20P=C4=83tru?= <80193149+MihaiPMC@users.noreply.github.com> Date: Sat, 7 Jun 2025 18:37:13 +0200 Subject: [PATCH 1/4] Show inventory overlay --- include/Game.hpp | 4 ++++ include/Zoo.hpp | 2 ++ src/Game.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++---- src/Zoo.cpp | 22 ++++++++++++++++++ 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/include/Game.hpp b/include/Game.hpp index 6212ced..44f1d5d 100644 --- a/include/Game.hpp +++ b/include/Game.hpp @@ -36,6 +36,8 @@ class Game void syncZooDataForRendering(); + void prepareInventoryDisplay(); + sf::RenderWindow m_window; unsigned int m_windowWidth, m_windowHeight; sf::Font m_font; @@ -93,4 +95,6 @@ class Game bool m_showingInventory; sf::RectangleShape m_showInventoryButton; sf::Text m_showInventoryButtonText; + sf::RectangleShape m_inventoryBackground; + std::vector m_inventoryTexts; }; \ No newline at end of file diff --git a/include/Zoo.hpp b/include/Zoo.hpp index cab6282..6c313bb 100644 --- a/include/Zoo.hpp +++ b/include/Zoo.hpp @@ -97,6 +97,8 @@ class Zoo void syncInventoryWithHabitats(); void displayAllInventories() const; + std::string getInventorySummary() const; + // Methods using template functions float calculateAverageAnimalHealth() const; int calculateTotalAnimalValue() const; diff --git a/src/Game.cpp b/src/Game.cpp index 41b9aa5..7a00d68 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -67,7 +67,9 @@ Game::Game() m_isDeletingObject(false), m_deletingObjectIndex(-1), m_zoo("Default Zoo", {}, 0, true), - m_showingInventory(false) + m_showingInventory(false), + m_inventoryBackground(), + m_inventoryTexts() { m_window.create(sf::VideoMode(m_windowWidth, m_windowHeight), "Zoo Tycoon - Enter Zoo Name"); if (!m_font.loadFromFile("fonts/DUSHICK.otf")) @@ -199,6 +201,10 @@ Game::Game() m_showInventoryButton.getPosition().y + (m_showInventoryButton.getSize().y - textBounds.height) / 2 - 5 ); + m_inventoryBackground.setFillColor(sf::Color(0, 0, 0, 200)); + m_inventoryBackground.setOutlineColor(sf::Color::White); + m_inventoryBackground.setOutlineThickness(2); + loadTexture(m_pathTexture, "images/path.png", "../images/path.png", sf::Color(153, 102, 51)); m_statusMessage.setFont(m_font); @@ -252,9 +258,8 @@ void Game::processEvents() if (m_showInventoryButton.getGlobalBounds().contains(mousePos.x, mousePos.y)) { m_showingInventory = !m_showingInventory; if (m_showingInventory) { - m_zoo.syncInventoryWithHabitats(); - m_zoo.displayAllInventories(); - m_statusMessage.setString("Inventory displayed in console"); + prepareInventoryDisplay(); + m_statusMessage.setString("Showing inventory"); m_statusMessage.setFillColor(sf::Color::Green); } else { m_statusMessage.setString(""); @@ -718,6 +723,9 @@ void Game::handleResize(unsigned int width, unsigned int height) m_showInventoryButton.getPosition().x + (m_showInventoryButton.getSize().x - textBounds.width) / 2, m_showInventoryButton.getPosition().y + (m_showInventoryButton.getSize().y - textBounds.height) / 2 - 5 ); + + if (m_showingInventory) + prepareInventoryDisplay(); float btnWidth = 120, btnHeight = 40; float startX = m_buildHabitatButton.getPosition().x; float startY = m_buildHabitatButton.getPosition().y + m_buildHabitatButton.getSize().y + 10; @@ -1196,6 +1204,13 @@ void Game::render() m_window.draw(m_animalOptionTexts[i]); } + if (m_showingInventory) + { + m_window.draw(m_inventoryBackground); + for (const auto &text : m_inventoryTexts) + m_window.draw(text); + } + sf::Text budgetText; budgetText.setFont(m_font); budgetText.setCharacterSize(20); @@ -1240,4 +1255,41 @@ bool Game::loadTexture(sf::Texture& texture, const std::string& primaryPath, con texture.loadFromImage(fallbackImage); std::cout << "Using fallback texture" << std::endl; return false; +} + +void Game::prepareInventoryDisplay() +{ + m_inventoryTexts.clear(); + m_zoo.syncInventoryWithHabitats(); + std::string summary = m_zoo.getInventorySummary(); + std::istringstream iss(summary); + std::string line; + float padding = 10.f; + float yOffset = padding; + float maxWidth = 0.f; + while (std::getline(iss, line)) + { + sf::Text text; + text.setFont(m_font); + text.setCharacterSize(14); + text.setFillColor(sf::Color::White); + text.setString(line); + m_inventoryTexts.push_back(text); + float w = text.getLocalBounds().width; + if (w > maxWidth) + maxWidth = w; + } + + float backgroundWidth = maxWidth + 2 * padding; + float backgroundHeight = (m_inventoryTexts.size() * 18.f) + 2 * padding; + m_inventoryBackground.setSize(sf::Vector2f(backgroundWidth, backgroundHeight)); + m_inventoryBackground.setPosition((m_windowWidth - backgroundWidth) / 2.f, + (m_windowHeight - backgroundHeight) / 2.f); + + float currentY = m_inventoryBackground.getPosition().y + padding; + for (auto &text : m_inventoryTexts) + { + text.setPosition(m_inventoryBackground.getPosition().x + padding, currentY); + currentY += 18.f; + } } \ No newline at end of file diff --git a/src/Zoo.cpp b/src/Zoo.cpp index aec0344..7efc290 100644 --- a/src/Zoo.cpp +++ b/src/Zoo.cpp @@ -4,6 +4,7 @@ #include "../include/exception/AnimalException.hpp" #include #include +#include Zoo::Zoo(const std::string &name, const std::vector &habitats, int visitor_count, bool is_open, float budget) : m_name(name), m_habitats(habitats), m_visitorCount(visitor_count), m_isOpen(is_open), m_budget(budget) @@ -135,6 +136,27 @@ void Zoo::displayAllInventories() const { m_habitatInventory.displayInventory(); } +std::string Zoo::getInventorySummary() const { + std::ostringstream oss; + oss << "=== " << m_allAnimalsInventory.getName() << " (" << m_allAnimalsInventory.getCount() + << "/" << m_allAnimalsInventory.getCapacity() << ") ===\n"; + size_t idx = 1; + for (const auto &animal : m_allAnimalsInventory.getItems()) { + if (animal) { + oss << idx++ << ". " << *animal << "\n"; + } + } + oss << "\n=== " << m_habitatInventory.getName() << " (" << m_habitatInventory.getCount() + << "/" << m_habitatInventory.getCapacity() << ") ===\n"; + idx = 1; + for (const auto &hab : m_habitatInventory.getItems()) { + if (hab) { + oss << idx++ << ". " << *hab << "\n"; + } + } + return oss.str(); +} + bool Zoo::spendMoney(float amount) { if (m_budget >= amount) From 5332e700fe6b1789d337c69800cf9fc5f9e42d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihai=20P=C4=83tru?= <80193149+MihaiPMC@users.noreply.github.com> Date: Sat, 7 Jun 2025 18:40:45 +0200 Subject: [PATCH 2/4] Remove unused variable from inventory overlay setup --- src/Game.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Game.cpp b/src/Game.cpp index 7a00d68..ac6e41f 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1265,7 +1265,6 @@ void Game::prepareInventoryDisplay() std::istringstream iss(summary); std::string line; float padding = 10.f; - float yOffset = padding; float maxWidth = 0.f; while (std::getline(iss, line)) { From 8d091487e290579d18209c64d7e54fe2e86db215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihai=20P=C4=83tru?= <80193149+MihaiPMC@users.noreply.github.com> Date: Sat, 7 Jun 2025 18:46:35 +0200 Subject: [PATCH 3/4] Add missing newline at EOF --- include/Game.hpp | 2 +- src/Game.cpp | 2 +- src/Zoo.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/Game.hpp b/include/Game.hpp index 44f1d5d..84325d7 100644 --- a/include/Game.hpp +++ b/include/Game.hpp @@ -97,4 +97,4 @@ class Game sf::Text m_showInventoryButtonText; sf::RectangleShape m_inventoryBackground; std::vector m_inventoryTexts; -}; \ No newline at end of file +}; diff --git a/src/Game.cpp b/src/Game.cpp index ac6e41f..e788bb4 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1291,4 +1291,4 @@ void Game::prepareInventoryDisplay() text.setPosition(m_inventoryBackground.getPosition().x + padding, currentY); currentY += 18.f; } -} \ No newline at end of file +} diff --git a/src/Zoo.cpp b/src/Zoo.cpp index 7efc290..d32668e 100644 --- a/src/Zoo.cpp +++ b/src/Zoo.cpp @@ -461,4 +461,4 @@ void Zoo::highlightHabitatAt(sf::RenderWindow& window, int tileSize, int index, if (index >= 0 && index < static_cast(m_habitats.size())) { m_habitats[index].highlightHabitat(window, tileSize, color, 2.0f); } -} \ No newline at end of file +} From 686d0af6e911bbc1d8eb434738be5c3ab75e62af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mihai=20P=C4=83tru?= <80193149+MihaiPMC@users.noreply.github.com> Date: Sat, 7 Jun 2025 19:09:32 +0200 Subject: [PATCH 4/4] Implement remaining Zoo metrics --- src/Zoo.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/Zoo.cpp b/src/Zoo.cpp index d32668e..a8db9c4 100644 --- a/src/Zoo.cpp +++ b/src/Zoo.cpp @@ -462,3 +462,59 @@ void Zoo::highlightHabitatAt(sf::RenderWindow& window, int tileSize, int index, m_habitats[index].highlightHabitat(window, tileSize, color, 2.0f); } } +float Zoo::calculateAverageAnimalHealth() const { + int count = 0; + float total = 0.f; + for (const auto& habitat : m_habitats) { + for (const auto& animal : habitat.getAnimals()) { + if (animal) { + total += animal->getIsHealthy(); + ++count; + } + } + } + return count > 0 ? total / count : 0.f; +} + +int Zoo::calculateTotalAnimalValue() const { + int total = 0; + for (const auto& habitat : m_habitats) { + for (const auto& animal : habitat.getAnimals()) { + if (animal) total += animal->getPrice(); + } + } + return total; +} + +float Zoo::calculateAverageHabitatCleanliness() const { + if (m_habitats.empty()) return 0.f; + float total = 0.f; + for (const auto& habitat : m_habitats) { + total += habitat.getCleanlinessLevel(); + } + return total / static_cast(m_habitats.size()); +} + +int Zoo::calculateTotalHabitatCapacity() const { + int total = 0; + for (const auto& habitat : m_habitats) { + total += habitat.getCapacity(); + } + return total; +} + +void Zoo::displayHealthyAnimals(float minHealthThreshold) const { + std::cout << "\nAnimals with health >= " << minHealthThreshold << ':' << std::endl; + m_allAnimalsInventory.forEachItem([&](const std::shared_ptr& animal){ + if (animal && animal->getIsHealthy() >= minHealthThreshold) + std::cout << *animal << std::endl; + }); +} + +void Zoo::displayExpensiveAnimals(int minPrice) const { + std::cout << "\nAnimals costing at least $" << minPrice << ':' << std::endl; + m_allAnimalsInventory.forEachItem([&](const std::shared_ptr& animal){ + if (animal && animal->getPrice() >= minPrice) + std::cout << *animal << std::endl; + }); +}