diff --git a/src/Rpg/dialogueSystem/DialogueActionExecutor.cpp b/src/Rpg/dialogueSystem/DialogueActionExecutor.cpp index aae8a1d..b6f8809 100644 --- a/src/Rpg/dialogueSystem/DialogueActionExecutor.cpp +++ b/src/Rpg/dialogueSystem/DialogueActionExecutor.cpp @@ -54,7 +54,7 @@ void DialogueActionExecutor::executeAction(const DialogueAction& action) { if (itemId != -1) mInventory.removeItemById(itemId, action.value); } else if (action.type == "change_crystals") { - mRpgEngine.changeCrystals(action.value); + mRpgEngine.addCrystals(action.value); } else if (action.type == "set_chapter") { mStoryManager.setChapter(action.value); } else { diff --git a/src/Rpg/gamengine/RPGEngine.cpp b/src/Rpg/gamengine/RPGEngine.cpp index ae0a900..f372ba8 100755 --- a/src/Rpg/gamengine/RPGEngine.cpp +++ b/src/Rpg/gamengine/RPGEngine.cpp @@ -47,7 +47,8 @@ static bool intersects(const sf::FloatRect& rect1, const sf::FloatRect& rect2) { RPGEngine::RPGEngine(sf::RenderWindow& window, GameManager* gameManager) : mWindow(window), mTimeSystem(0.36f), - mCharacter(sf::Vector2f(295.f, 290.f)), + mLevelCompleteMenu(window, nullptr, this, gameManager, 2, false), + mCharacter(sf::Vector2f(295.f, 290.f), &mInventory, &mLevelCompleteMenu), mView(sf::Vector2f(400.f, 300.f), sf::Vector2f(740.f, 420.f)), mFixedCamera(sf::Vector2f(0.f, 0.f), sf::Vector2f(740.f, 420.f)), mCameraFixedPosition(sf::Vector2f(0.f, 0.f)), @@ -57,7 +58,7 @@ RPGEngine::RPGEngine(sf::RenderWindow& window, GameManager* gameManager) mSaveNumber(0), mMiraStanton(sf::Vector2f(1000.0f, 900.0f), "mira_stanton"), mElliotMarlowe(sf::Vector2f(100.0f, 0.0f), "elliot_marlowe"), - mGarrickStone(sf::Vector2f(-100.0f, 0.0f), "garrick_stone",gameManager), + mGarrickStone(sf::Vector2f(-100.0f, 0.0f), "garrick_stone", gameManager), mVincentHale(sf::Vector2f(600.0f, 400.0f), "vincent_hale"), mSeraphinaLumeris(sf::Vector2f(-20.0f, 980.0f), "seraphina_lumeris"), mNPCManager(mStoryManager, mDialogueDatabase, *this, mInventory), @@ -77,7 +78,7 @@ RPGEngine::RPGEngine(sf::RenderWindow& window, GameManager* gameManager) mStructureIndex(-1), mCrystals(100), mStorageCapacity(500), - mCurrentLevel(1), + mCurrentTowerDefenseLevel(1), mChapter(1), mSelectedChoice(0), mPaused(true), @@ -102,7 +103,7 @@ RPGEngine::RPGEngine(sf::RenderWindow& window, GameManager* gameManager) } }, mWaypointManager}, mZoneManager(mGameContext, 1), - mStartTowerDefenseMenu(window, mAvailableTowers, this, gameManager, mCurrentLevel, mCrystals), + mStartTowerDefenseMenu(window, mAvailableTowers, this, gameManager, mCurrentTowerDefenseLevel, mCrystals), mBankMenu(window, mCrystals, mStorageCapacity, mTimeSystem), mShopMenu(window, mInventory, mTimeSystem, 5, mCrystals), mAnalyzeMenu(window, mInventory, mTimeSystem, mAvailableTowers, sf::Vector2f(70.0f, 70.0f), mCrystals) { @@ -363,6 +364,8 @@ void RPGEngine::processEvents() { if (mShowChestMenu) mChestMenu.handleMouseClick(mousePos); + mLevelCompleteMenu.handleMouseClick(mousePos); + if(!mShowMenu && !mShowStartMenu && !mShowBankMenu && !mShowShopMenu && !mShowAnalyzeMenu && !mShowChestMenu && !mShowDialogue) { int slot = mHotbar.contains(mousePos); mHotbar.setHoveredSlot(slot); @@ -384,115 +387,120 @@ void RPGEngine::update() { if (!mShowShopMenu) { if (!mShowAnalyzeMenu) { if (!mShowChestMenu) { - sf::Vector2f previousPosition = mCharacter.getPosition(); + if (!mLevelCompleteMenu.isActive()) { + sf::Vector2f previousPosition = mCharacter.getPosition(); - if (!mShowDialogue) { - mHotbar.update(); - } + if (!mShowDialogue) { + mHotbar.update(); + } - mTransitionSystem.update(dt); + mTransitionSystem.update(dt); - mTimeSystem.update(dt); + mTimeSystem.update(dt); - if (mTimeSystem.getHour() == 0 && mTimeSystem.getMinute() == 0) - mShopMenu.regenerateIds(); + if (mTimeSystem.getHour() == 0 && mTimeSystem.getMinute() == 0) + mShopMenu.regenerateIds(); - if (mTransitionSystem.isTransitioning()) - return; + if (mTransitionSystem.isTransitioning()) + return; - mCharacter.update(dt, mShowDialogue); - mZoneManager.update(mCharacter.getPosition()); + mCharacter.update(dt, mShowDialogue); + mZoneManager.update(mCharacter.getPosition()); - if (mZoneManager.checkCollision(mCharacter.getBounds())) - mCharacter.setPosition(previousPosition); + if (mZoneManager.checkCollision(mCharacter.getBounds())) + mCharacter.setPosition(previousPosition); - for (auto& npc : mNPCManager.getNPCs()) { - if (npc->getBounds().intersects(mCharacter.getBounds())) { - sf::Vector2f npcPos = npc->getPosition(); - sf::Vector2f direction = previousPosition - npcPos; - float distance = std::sqrt(direction.x * direction.x + direction.y * direction.y); + for (auto& npc : mNPCManager.getNPCs()) { + if (npc->getBounds().intersects(mCharacter.getBounds())) { + sf::Vector2f npcPos = npc->getPosition(); + sf::Vector2f direction = previousPosition - npcPos; + float distance = std::sqrt(direction.x * direction.x + direction.y * direction.y); - if (distance < 10.0f) { // Push the player away from the npc with a threshold - direction /= distance; - previousPosition += direction * 5.0f * dt; - mCharacter.setPosition(previousPosition); + if (distance < 10.0f) { // Push the player away from the npc with a threshold + direction /= distance; + previousPosition += direction * 5.0f * dt; + mCharacter.setPosition(previousPosition); + } } - } - if (npc->isPlayerClose(mCharacter.getPosition())) { - if (mShowDialogue) - npc->setInteract(false); + if (npc->isPlayerClose(mCharacter.getPosition())) { + if (mShowDialogue) + npc->setInteract(false); + else + npc->setInteract(true); + } else - npc->setInteract(true); + npc->setInteract(false); } - else - npc->setInteract(false); - } - mNPCManager.update(dt); - mView.setCenter(mCharacter.getCenterPosition()); + mNPCManager.update(dt); + mView.setCenter(mCharacter.getCenterPosition()); - if (mCameraFixedPosition.x != 0.f || mCameraFixedPosition.y != 0.f) - mFixedCamera.setCenter(mCameraFixedPosition); - else - mFixedCamera.setCenter(mCharacter.getCenterPosition()); + if (mCameraFixedPosition.x != 0.f || mCameraFixedPosition.y != 0.f) + mFixedCamera.setCenter(mCameraFixedPosition); + else + mFixedCamera.setCenter(mCharacter.getCenterPosition()); - if (!mNPCManager.playerClose(mCharacter.getPosition())) { - mShowDialogue = false; - } + if (!mNPCManager.playerClose(mCharacter.getPosition())) { + mShowDialogue = false; + } - sf::FloatRect playerBounds = mCharacter.getBounds(); - sf::Vector2f playerCenter = {playerBounds.left + playerBounds.width / 2.f, playerBounds.top + playerBounds.height / 2.f}; - - for (auto it = mDroppedItems.begin(); it != mDroppedItems.end();) { - sf::Vector2f itemCenter = it->getCenterPosition(); - float distance = std::sqrt( - std::pow(playerCenter.x - itemCenter.x, 2.f) + - std::pow(playerCenter.y - itemCenter.y, 2.f) - ); - - if (it->getPickUpCap()) { - if (distance < 28.f) { - auto itemClone = it->getItem()->clone(); - mInventory.addItem(std::move(itemClone), it->getQuantity()); - it = mDroppedItems.erase(it); - continue; + sf::FloatRect playerBounds = mCharacter.getBounds(); + sf::Vector2f playerCenter = {playerBounds.left + playerBounds.width / 2.f, playerBounds.top + playerBounds.height / 2.f}; + + for (auto it = mDroppedItems.begin(); it != mDroppedItems.end();) { + sf::Vector2f itemCenter = it->getCenterPosition(); + float distance = std::sqrt( + std::pow(playerCenter.x - itemCenter.x, 2.f) + + std::pow(playerCenter.y - itemCenter.y, 2.f) + ); + + if (it->getPickUpCap()) { + if (distance < 28.f) { + auto itemClone = it->getItem()->clone(); + mInventory.addItem(std::move(itemClone), it->getQuantity()); + it = mDroppedItems.erase(it); + continue; + } + } else { + if (distance > 28.f) + it->setPickUpCap(true); } - } else { - if (distance > 28.f) - it->setPickUpCap(true); + ++it; } - ++it; - } - mShowInteract = false; + mShowInteract = false; - for (auto& entity : mZoneManager.getEntities()) { - if (!entity->isInteractable()) - continue; + for (auto& entity : mZoneManager.getEntities()) { + if (!entity->isInteractable()) + continue; - if (entity->getInteractBounds().intersects(mCharacter.getInteractBounds())) { - mShowInteract = true; + if (entity->getInteractBounds().intersects(mCharacter.getInteractBounds())) { + mShowInteract = true; - mInteractPos = entity->getInteractPosition(); + mInteractPos = entity->getInteractPosition(); - mInteractCircle.setPosition({mInteractPos.x + - entity->getInteractBounds().width + 1.5f, mInteractPos.y - 12.f}); + mInteractCircle.setPosition({mInteractPos.x + + entity->getInteractBounds().width + 1.5f, mInteractPos.y - 12.f}); - mInteractText.setPosition({ mInteractCircle.getPosition().x + 5.9f, - mInteractCircle.getPosition().y + 2.8f}); + mInteractText.setPosition({ mInteractCircle.getPosition().x + 5.9f, + mInteractCircle.getPosition().y + 2.8f}); - break; + break; + } } - } - if (!mShowInteract) { - mInteractPos = { 0.f, 0.f }; - mInteractCircle.setPosition(mInteractPos); - mInteractText.setPosition(mInteractPos); - } + if (!mShowInteract) { + mInteractPos = { 0.f, 0.f }; + mInteractCircle.setPosition(mInteractPos); + mInteractText.setPosition(mInteractPos); + } - mAnalyzeMenu.update(); + mAnalyzeMenu.update(); + } else { + sf::Vector2f mousePos = mWindow.mapPixelToCoords(sf::Mouse::getPosition(mWindow)); + mLevelCompleteMenu.updateHover(mousePos); + } } else { sf::Vector2f mousePos = mWindow.mapPixelToCoords(sf::Mouse::getPosition(mWindow)); mChestMenu.updateHover(mousePos); @@ -644,6 +652,8 @@ void RPGEngine::render() { if(!mShowDialogue) mHotbar.render(mWindow); + mLevelCompleteMenu.render(mWindow); + mTransitionSystem.render(mWindow); renderDateTime(mWindow, mFont, currentDate, currentTime); @@ -853,8 +863,8 @@ void RPGEngine::saveGame() { for (int i = 0; i < droppedItemId.size(); ++i) std::cout << droppedItemId[i] << " " << droppedItemXPos[i] << " " << droppedItemYPos[i] << " " << droppedItemQuantity[i] << std::endl;*/ - mSaveSystem.save(mCharacter.getPosition(), mCharacter.getAnimation(), - npcPositions, npcWaypoints, mCrystals, + mSaveSystem.save(mCharacter.getPosition(), mCharacter.getAnimation(), mCharacter.getLevel(), mCharacter.getXp(), + mCurrentTowerDefenseLevel, npcPositions, npcWaypoints, mCrystals, year, day, hour, minute, bankBalance, hasBorrowActive, penalty, interest, amountToRepay, daysToRepayment, startYear, startDay, startHour, startMinute, inventoryItemId, inventoryItemQuantity, @@ -867,7 +877,8 @@ void RPGEngine::saveGame() { void RPGEngine::loadGame() { sf::Vector2f playerPosition; - int playerAnimation; + int playerAnimation, playerLevel, playerXp; + int towerDefenseLevel; std::vector npcPositions; std::vector npcWaypoints; int crystals, year, day, hour, minute, bankBalance, penalty, interest, @@ -885,8 +896,8 @@ void RPGEngine::loadGame() { std::vector flagKeys; std::vector flagValues; - if (mSaveSystem.load(playerPosition, playerAnimation, - npcPositions, npcWaypoints, crystals, year, + if (mSaveSystem.load(playerPosition, playerAnimation, playerLevel, playerXp, + towerDefenseLevel, npcPositions, npcWaypoints, crystals, year, day, hour, minute, bankBalance, hasBorrowActive, penalty, interest, amountToRepay, daysToRepayment, startYear, startDay, startHour, startMinute, inventoryItemId, inventoryItemQuantity, @@ -901,6 +912,9 @@ void RPGEngine::loadGame() { mDroppedItems.clear(); mCharacter.setAnimation(playerAnimation); + mCharacter.setLevel(playerLevel); + mCharacter.setXp(playerXp); + mCurrentTowerDefenseLevel = towerDefenseLevel; mIsInsideAStructure = insideStructure; mStructureIndex = structureIndex; @@ -1105,7 +1119,7 @@ void RPGEngine::setFlag(std::string name, bool value) { mShowChestMenu = value; } -void RPGEngine::changeCrystals(int value) { +void RPGEngine::addCrystals(int value) { mCrystals += value; } @@ -1203,3 +1217,11 @@ sf::Vector2f RPGEngine::calculateDropPosition() { return validPos - sf::Vector2f(8.f, 8.f); } +void RPGEngine::addXp(int xp) { + mCharacter.getLevelSystem().addXp(xp); +} + +void RPGEngine::advanceTowerDefenseLevel() { + mStartTowerDefenseMenu.advanceLevel(); +} + diff --git a/src/Rpg/gamengine/RPGEngine.h b/src/Rpg/gamengine/RPGEngine.h index 32e439b..2edd647 100644 --- a/src/Rpg/gamengine/RPGEngine.h +++ b/src/Rpg/gamengine/RPGEngine.h @@ -26,6 +26,7 @@ #include "../menues/ShopMenu.h" #include "../menues/AnalyzeMenu.h" #include "../menues/ChestMenu.h" +#include "../../TowerDefense/menues/LevelCompleteMenu.h" #include "../map/entities/DrawableEntity.h" #include "../map/buildings/MCHouse.h" #include "../map/buildings/MCHouseInt.h" @@ -59,8 +60,10 @@ class RPGEngine { void newGame(); void setSaveNumber(int saveNumber); void setFlag(std::string name, bool value); - void changeCrystals(int value); + void addCrystals(int value); void setCrystals(int crystals); + void addXp(int xp); + void advanceTowerDefenseLevel(); void initialize(); void uninitialize(); @@ -96,7 +99,7 @@ class RPGEngine { GameManager* mGameManager; int mCrystals; - int mCurrentLevel; + int mCurrentTowerDefenseLevel; std::vector mAvailableTowers; int mChapter; @@ -118,6 +121,7 @@ class RPGEngine { BankMenu mBankMenu; AnalyzeMenu mAnalyzeMenu; ChestMenu mChestMenu; + LevelCompleteMenu mLevelCompleteMenu; NPC* mCurrentInteractingNPC; TimeSystem mTimeSystem; diff --git a/src/Rpg/mainCharacter/LevelSystem.cpp b/src/Rpg/mainCharacter/LevelSystem.cpp new file mode 100644 index 0000000..2c94d71 --- /dev/null +++ b/src/Rpg/mainCharacter/LevelSystem.cpp @@ -0,0 +1,60 @@ +#include "LevelSystem.h" +#include +#include "../inventory/items/TowerBlueprintEpic.h" + + +LevelSystem::LevelSystem(Inventory* inventory, LevelCompleteMenu* levelCompleteMenu, int maxLevel) + : mInventory(inventory), mLevelCompleteMenu(levelCompleteMenu), mCurrentXp(0), + mCurrentLevel(1), mMaxLevel(maxLevel) { + +} + +void LevelSystem::addXp(int xp) { + if (mCurrentLevel < mMaxLevel) { + mCurrentXp += xp; + checkLevelUp(); + } +} + +void LevelSystem::checkLevelUp() { + while (mCurrentLevel < mMaxLevel && mCurrentXp >= getXpForNextLevel()) { + mCurrentXp -= getXpForNextLevel(); + mCurrentLevel++; + + grantRewards(mCurrentLevel); + } +} + +void LevelSystem::grantRewards(int level) { + mLevelCompleteMenu->setLevel(level); + mLevelCompleteMenu->refresh(); + mLevelCompleteMenu->setActive(true); +} + +int LevelSystem::getCurrentXp() const { + return mCurrentXp; +} + +int LevelSystem::getLevel() const { + return mCurrentLevel; +} + +void LevelSystem::setLevel(int level) { + mCurrentLevel = level; +} + +int LevelSystem::getXpForNextLevel() const { + return static_cast(50.f * std::pow(mCurrentLevel, 1.3f)); +} + +float LevelSystem::getXpPercentage() const { + if (mCurrentLevel >= mMaxLevel) + return 1.f; + + return static_cast(mCurrentXp) / static_cast(getXpForNextLevel()); +} + +void LevelSystem::setXp(int xp) { + mCurrentXp = xp; +} + diff --git a/src/Rpg/mainCharacter/LevelSystem.h b/src/Rpg/mainCharacter/LevelSystem.h new file mode 100644 index 0000000..39ffa49 --- /dev/null +++ b/src/Rpg/mainCharacter/LevelSystem.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include "../inventory/Inventory.h" +#include "../../TowerDefense/menues/LevelCompleteMenu.h" + +class LevelSystem { +public: + LevelSystem(Inventory* inventory, LevelCompleteMenu* levelCompleteMenu, int maxLevel = 50); + + void addXp(int xp); + + int getLevel() const; + void setLevel(int level); + + int getCurrentXp() const; + int getXpForNextLevel() const; + float getXpPercentage() const; + void setXp(int xp); + + void grantRewards(int level); + +private: + void checkLevelUp(); + + int mCurrentLevel; + int mCurrentXp; + int mMaxLevel; + + Inventory* mInventory; + LevelCompleteMenu* mLevelCompleteMenu; +}; diff --git a/src/Rpg/mainCharacter/MainCharacter.cpp b/src/Rpg/mainCharacter/MainCharacter.cpp index eee1901..1870b24 100644 --- a/src/Rpg/mainCharacter/MainCharacter.cpp +++ b/src/Rpg/mainCharacter/MainCharacter.cpp @@ -1,9 +1,10 @@ #include "MainCharacter.h" +#include "LevelSystem.h" #include #include -MainCharacter::MainCharacter(const sf::Vector2f& position) - : mPosition(position), mSpeed(142.0f), mPriority(0) { +MainCharacter::MainCharacter(const sf::Vector2f& position, Inventory* inventory, LevelCompleteMenu* levelCompleteMenu) + : mPosition(position), mSpeed(142.0f), mPriority(0), mLevelSystem(inventory, levelCompleteMenu) { mCollisionZone.setSize(sf::Vector2f(24.f, 16.f)); mCollisionZone.setPosition(sf::Vector2f(mPosition.x + 21.f, mPosition.y + 47.f)); mCollisionZone.setFillColor(sf::Color::Red); @@ -164,3 +165,27 @@ int MainCharacter::getAnimation() { return 0; } +LevelSystem& MainCharacter::getLevelSystem() { + return mLevelSystem; +} + +int MainCharacter::getLevel() const { + return mLevelSystem.getLevel(); +} + +void MainCharacter::setLevel(int level) { + mLevelSystem.setLevel(level); +} + +int MainCharacter::getXp() const { + return mLevelSystem.getCurrentXp(); +} + +int MainCharacter::getXpForNextLevel() const { + return mLevelSystem.getXpForNextLevel(); +} + +void MainCharacter::setXp(int xp) { + mLevelSystem.setXp(xp); +} + diff --git a/src/Rpg/mainCharacter/MainCharacter.h b/src/Rpg/mainCharacter/MainCharacter.h index f2ad8fc..8ed35f4 100644 --- a/src/Rpg/mainCharacter/MainCharacter.h +++ b/src/Rpg/mainCharacter/MainCharacter.h @@ -2,10 +2,13 @@ #include #include "../../Animation.h" #include "../map/entities/DrawableEntity.h" +#include "../inventory/Inventory.h" +#include "LevelSystem.h" +#include "../../TowerDefense/menues/LevelCompleteMenu.h" class MainCharacter : public DrawableEntity { public: - MainCharacter(const sf::Vector2f& position); + MainCharacter(const sf::Vector2f& position, Inventory* inventory, LevelCompleteMenu* levelCompleteMenu); void update(float dt, bool inDialogue); void render(sf::RenderWindow& window) override; @@ -23,6 +26,14 @@ class MainCharacter : public DrawableEntity { void setAnimation(int animation); int getAnimation(); + LevelSystem& getLevelSystem(); + int getLevel() const; + void setLevel(int level); + + int getXp() const; + int getXpForNextLevel() const; + void setXp(int xp); + private: enum class AnimationIndex { IdleUp, @@ -39,6 +50,8 @@ class MainCharacter : public DrawableEntity { float mSpeed; int mPriority; + LevelSystem mLevelSystem; + sf::Keyboard::Key mLastDirection = sf::Keyboard::A; sf::Sprite mSprite; Animation mAnimations[int(AnimationIndex::Count)]; diff --git a/src/Rpg/menues/ShopMenu.cpp b/src/Rpg/menues/ShopMenu.cpp index 8d4db9a..7fc4ba9 100755 --- a/src/Rpg/menues/ShopMenu.cpp +++ b/src/Rpg/menues/ShopMenu.cpp @@ -378,9 +378,9 @@ void ShopMenu::updateTooltip(int slot, int id) { std::string tooltipText; if (id == 1) tooltipText = "Cost: 5\nWood\nA piece of wood, useful for crafting."; else if (id == 2) tooltipText = "Cost: 50\nTower Blueprint\nCan be used to unlock towers!"; - else if (id == 3) tooltipText = "Cost: 100\nTower Blueprint Rare\nCan be used to unlock rare towers!"; - else if (id == 4) tooltipText = "Cost: 150\nTower Blueprint Epic\nCan be used to unlock epic towers!"; - else if (id == 5) tooltipText = "Cost: 250\nTower Blueprint Mythic\nCan be used to unlock mythic towers!"; + else if (id == 3) tooltipText = "Cost: 100\nRare Tower Blueprint\nCan be used to unlock rare towers!"; + else if (id == 4) tooltipText = "Cost: 150\nEpic Tower Blueprint\nCan be used to unlock epic towers!"; + else if (id == 5) tooltipText = "Cost: 250\nMythic Tower Blueprint\nCan be used to unlock mythic towers!"; else tooltipText = "Nothing here!"; mTooltipText.setString(tooltipText); diff --git a/src/Rpg/menues/StartTowerDefenseMenu.cpp b/src/Rpg/menues/StartTowerDefenseMenu.cpp index 57b4d86..23d74b3 100644 --- a/src/Rpg/menues/StartTowerDefenseMenu.cpp +++ b/src/Rpg/menues/StartTowerDefenseMenu.cpp @@ -7,7 +7,7 @@ StartTowerDefenseMenu::StartTowerDefenseMenu(sf::RenderWindow& window, std::vect RPGEngine* gameEngine, GameManager* gameManager, int level, int crystals) : mStartButton(sf::Vector2f(826.f, 570.f), sf::Vector2f(80.0f, 30.0f), "Start"), mGameManager(gameManager), mAvailableTowers(availableTowers), mCrystals(crystals), - mLevel(level), mGameEngine(gameEngine), mShowText(false) { + mLevel(level), mGameEngine(gameEngine), mShowText(false), mWindow(window) { if (!mFont.loadFromFile("assets/fonts/gameFont.ttf")) std::cout << "Couldn't load font from file" << std::endl; @@ -29,31 +29,6 @@ StartTowerDefenseMenu::StartTowerDefenseMenu(sf::RenderWindow& window, std::vect mMinimapBorder.setOutlineColor(sf::Color::White); mMinimapBorder.setOutlineThickness(1.7f); - const auto& paths = getPaths()[level - 1]; - const float scaleX = mMinimapBorder.getSize().x / window.getSize().x; - const float scaleY = mMinimapBorder.getSize().y / window.getSize().y; - - for (const auto& path : paths) { - for (size_t i = 0; i < path.size() - 1; ++i) { - sf::RectangleShape segment; - segment.setFillColor(sf::Color(128, 128, 128)); - - sf::Vector2f start(path[i].x * scaleX + mMinimapBorder.getPosition().x, path[i].y * scaleY + mMinimapBorder.getPosition().y); - sf::Vector2f end(path[i + 1].x * scaleX + mMinimapBorder.getPosition().x, path[i + 1].y * scaleY + mMinimapBorder.getPosition().y); - - if (start.x == end.x) { - // Vertical path - segment.setSize({50.f * scaleX, std::abs(end.y - start.y)}); - segment.setPosition(start.x - 25.f * scaleX, std::min(start.y, end.y)); - } else { - // Horizontal path - segment.setSize({std::abs(end.x - start.x), 50.f * scaleY}); - segment.setPosition(std::min(start.x, end.x), start.y - 25.f * scaleY); - } - mMinimapPaths.push_back(segment); - } - } - mDifficultyText.setFont(mFont); mDifficultyText.setCharacterSize(16); mDifficultyText.setPosition(sf::Vector2f(mMinimapBorder.getPosition().x + mMinimapBorder.getSize().x + 34.f, @@ -61,45 +36,6 @@ StartTowerDefenseMenu::StartTowerDefenseMenu(sf::RenderWindow& window, std::vect mDifficultyText.setFillColor(sf::Color::White); mDifficultyText.setString("Difficuly"); - int currentDifficulty; - if (level == 1) - currentDifficulty = 2; - else - currentDifficulty = 3; - - float circleRadius = 8.f; - const sf::Vector2f startPos(mDifficultyText.getPosition().x, mDifficultyText.getPosition().y + 28.5f); - for (int i = 0; i < 5; ++i) { - sf::CircleShape circle(circleRadius); - circle.setPosition(startPos.x + i * (circleRadius * 2 + 6.35f), startPos.y); - circle.setFillColor(i < currentDifficulty ? sf::Color::White : sf::Color(100, 100, 100)); - mDifficultyCircles.push_back(circle); - } - - mTowerSlots.resize(6); - sf::Vector2f position(mMenuShape.getPosition().x + 50.f, mMenuShape.getPosition().y + mHoveredZoneShape.getSize().y + 50.f); - for (int i = 0; i < 6; ++i) { - mTowerSlots[i].setSize(sf::Vector2f(50.f, 50.f)); - mTowerSlots[i].setFillColor(sf::Color(0, 0, 0, 220)); - mTowerSlots[i].setOutlineColor(sf::Color::White); - mTowerSlots[i].setOutlineThickness(2.0f); - mTowerSlots[i].setPosition(position.x + i * 50.f, position.y); - } - mSelectedTowers.reserve(mTowerSlots.size()); - mSelectingTowerSlots.resize(availableTowers.size()); - sf::Vector2f position1(mMenuShape.getPosition().x + 50.f, mMenuShape.getPosition().y + mHoveredZoneShape.getSize().y + 150.f); - - int indent = 0; - for (int i = 0; i < availableTowers.size(); ++i) { - mSelectingTowerSlots[i].setSize(sf::Vector2f(50.f, 50.f)); - mSelectingTowerSlots[i].setFillColor(sf::Color(0, 0, 0, 220)); - mSelectingTowerSlots[i].setOutlineColor(sf::Color::White); - mSelectingTowerSlots[i].setOutlineThickness(2.0f); - if (i % 6 == 0 && i) - indent += 60; - mSelectingTowerSlots[i].setPosition(position1.x + i * 50.f, position1.y + indent); - } - mTitle.setFillColor(sf::Color::White); mTitle.setFont(mFont); mTitle.setCharacterSize(20); @@ -118,39 +54,17 @@ StartTowerDefenseMenu::StartTowerDefenseMenu(sf::RenderWindow& window, std::vect mCurrentLevelText.setFillColor(sf::Color::White); mCurrentLevelText.setFont(mFont); mCurrentLevelText.setCharacterSize(31); - std::string levelString = "Level " + std::to_string(level); - mCurrentLevelText.setString(levelString); - mCurrentLevelText.setPosition(sf::Vector2f(mMenuShape.getPosition().x + mMenuShape.getSize().x * 0.75f - - mCurrentLevelText.getLocalBounds().width / 2.f, - mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.15f)); - + mLevelDescriptionText.setFillColor(sf::Color::White); mLevelDescriptionText.setFont(mFont); mLevelDescriptionText.setCharacterSize(15); - std::string descriptionString = ""; - if(level == 1) - descriptionString = "There once was a ship that put to sea\nThe name of the ship was the Billy O Tea"; - - mLevelDescriptionText.setString(descriptionString); - mLevelDescriptionText.setPosition(sf::Vector2f(mMenuShape.getPosition().x + mMenuShape.getSize().x * 0.585f, - mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.3f)); - mLine.setFillColor(sf::Color(10, 10, 10, 100)); mLine.setSize(sf::Vector2f(2.9f, mMenuShape.getSize().y - mHoveredZoneShape.getSize().y)); mLine.setPosition(sf::Vector2f(mMenuShape.getPosition().x + mMenuShape.getSize().x / 2.f - mLine.getSize().x / 2.f, mMenuShape.getPosition().y + mHoveredZoneShape.getSize().y)); - mStartButton.setCallback([&]() { - if(!mSelectedTowers.empty()) { - mGameEngine->saveGame(); - mGameManager->switchToTowerDefense(mCrystals, mLevel, mSelectedTowers); - } else { - mErrorText.setFillColor(sf::Color::White); - mClock.restart(); - mShowText = true; - } - }); + refresh(); } void StartTowerDefenseMenu::render(sf::RenderWindow& window) { @@ -276,3 +190,107 @@ void StartTowerDefenseMenu::update(int crystals, std::vector& availableTowe }); } +void StartTowerDefenseMenu::advanceLevel() { + mLevel++; + refresh(); +} + +void StartTowerDefenseMenu::refresh() { + + const auto& paths = getPaths()[mLevel - 1]; + const float scaleX = mMinimapBorder.getSize().x / mWindow.getSize().x; + const float scaleY = mMinimapBorder.getSize().y / mWindow.getSize().y; + + for (const auto& path : paths) { + for (size_t i = 0; i < path.size() - 1; ++i) { + sf::RectangleShape segment; + segment.setFillColor(sf::Color(128, 128, 128)); + + sf::Vector2f start(path[i].x * scaleX + mMinimapBorder.getPosition().x, path[i].y * scaleY + mMinimapBorder.getPosition().y); + sf::Vector2f end(path[i + 1].x * scaleX + mMinimapBorder.getPosition().x, path[i + 1].y * scaleY + mMinimapBorder.getPosition().y); + + if (start.x == end.x) { + // Vertical path + segment.setSize({50.f * scaleX, std::abs(end.y - start.y)}); + segment.setPosition(start.x - 25.f * scaleX, std::min(start.y, end.y)); + } else { + // Horizontal path + segment.setSize({std::abs(end.x - start.x), 50.f * scaleY}); + segment.setPosition(std::min(start.x, end.x), start.y - 25.f * scaleY); + } + mMinimapPaths.push_back(segment); + } + } + + int currentDifficulty; + if (mLevel == 1) + currentDifficulty = 1; + else if (mLevel == 2) + currentDifficulty = 2; + else if (mLevel == 3) + currentDifficulty = 2; + else + currentDifficulty = 3; + + + float circleRadius = 8.f; + const sf::Vector2f startPos(mDifficultyText.getPosition().x, mDifficultyText.getPosition().y + 28.5f); + for (int i = 0; i < 5; ++i) { + sf::CircleShape circle(circleRadius); + circle.setPosition(startPos.x + i * (circleRadius * 2 + 6.35f), startPos.y); + circle.setFillColor(i < currentDifficulty ? sf::Color::White : sf::Color(100, 100, 100)); + mDifficultyCircles.push_back(circle); + } + + mTowerSlots.resize(6); + sf::Vector2f position(mMenuShape.getPosition().x + 50.f, mMenuShape.getPosition().y + mHoveredZoneShape.getSize().y + 50.f); + for (int i = 0; i < 6; ++i) { + mTowerSlots[i].setSize(sf::Vector2f(50.f, 50.f)); + mTowerSlots[i].setFillColor(sf::Color(0, 0, 0, 220)); + mTowerSlots[i].setOutlineColor(sf::Color::White); + mTowerSlots[i].setOutlineThickness(2.0f); + mTowerSlots[i].setPosition(position.x + i * 50.f, position.y); + } + mSelectedTowers.reserve(mTowerSlots.size()); + mSelectingTowerSlots.resize(mAvailableTowers.size()); + sf::Vector2f position1(mMenuShape.getPosition().x + 50.f, mMenuShape.getPosition().y + mHoveredZoneShape.getSize().y + 150.f); + + int indent = 0; + for (int i = 0; i < mAvailableTowers.size(); ++i) { + mSelectingTowerSlots[i].setSize(sf::Vector2f(50.f, 50.f)); + mSelectingTowerSlots[i].setFillColor(sf::Color(0, 0, 0, 220)); + mSelectingTowerSlots[i].setOutlineColor(sf::Color::White); + mSelectingTowerSlots[i].setOutlineThickness(2.0f); + if (i % 6 == 0 && i) + indent += 60; + mSelectingTowerSlots[i].setPosition(position1.x + i * 50.f, position1.y + indent); + } + + std::string levelString = "Level " + std::to_string(mLevel); + mCurrentLevelText.setString(levelString); + mCurrentLevelText.setPosition(sf::Vector2f(mMenuShape.getPosition().x + mMenuShape.getSize().x * 0.75f - + mCurrentLevelText.getLocalBounds().width / 2.f, + mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.15f)); + + std::string descriptionString = ""; + if(mLevel == 1) + descriptionString = "There once was a ship that put to sea\nThe name of the ship was the Billy O Tea"; + else + descriptionString = "Nothing here"; + + mLevelDescriptionText.setString(descriptionString); + mLevelDescriptionText.setPosition(sf::Vector2f(mMenuShape.getPosition().x + mMenuShape.getSize().x * 0.585f, + mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.3f)); + + mStartButton.setCallback([&]() { + if(!mSelectedTowers.empty()) { + mGameEngine->saveGame(); + mGameManager->switchToTowerDefense(mCrystals, mLevel, mSelectedTowers); + } else { + mErrorText.setFillColor(sf::Color::White); + mClock.restart(); + mShowText = true; + } + }); +} + diff --git a/src/Rpg/menues/StartTowerDefenseMenu.h b/src/Rpg/menues/StartTowerDefenseMenu.h index 782a050..19527b0 100644 --- a/src/Rpg/menues/StartTowerDefenseMenu.h +++ b/src/Rpg/menues/StartTowerDefenseMenu.h @@ -19,7 +19,12 @@ class StartTowerDefenseMenu { void updateHover(const sf::Vector2f& mousePos); void update(int crystals, std::vector& availableTowers); + void advanceLevel(); + void refresh(); + private: + sf::RenderWindow& mWindow; + sf::RectangleShape mMenuShape; sf::RectangleShape mHoveredZoneShape; sf::Text mTitle; diff --git a/src/Rpg/saveSystem/SaveSystem.cpp b/src/Rpg/saveSystem/SaveSystem.cpp index f37ddc4..5b678e0 100644 --- a/src/Rpg/saveSystem/SaveSystem.cpp +++ b/src/Rpg/saveSystem/SaveSystem.cpp @@ -7,8 +7,8 @@ SaveSystem::SaveSystem() : mSaveFilePath("") { } -void SaveSystem::save(const sf::Vector2f& playerPosition, const int& playerAnimation, - const std::vector& npcPositions, const std::vector& npcWaypoints, +void SaveSystem::save(const sf::Vector2f& playerPosition, const int& playerAnimation, const int& playerLevel, const int& playerXp, + const int& towerDefenseLevel, const std::vector& npcPositions, const std::vector& npcWaypoints, const int& crystals, const int& year, const int& day, const int& hour, const int& minute, const int& bankBalance, const int& hasBorrowActive, const int& penalty, const int& interest, const int& amountToRepay, const int& daysToRepayment, @@ -29,9 +29,10 @@ void SaveSystem::save(const sf::Vector2f& playerPosition, const int& playerAnima return; } - outFile << playerPosition.x << " " << playerPosition.y << " " << playerAnimation << std::endl; - outFile << npcPositions.size() << std::endl; + outFile << playerPosition.x << " " << playerPosition.y << " " << playerAnimation << " " << playerLevel << " " << playerXp << " " << std::endl; + outFile << towerDefenseLevel << std::endl; + outFile << npcPositions.size() << std::endl; for (size_t i = 0; i < npcPositions.size(); ++i) outFile << npcPositions[i].x << " " << npcPositions[i].y << " " << npcWaypoints[i] << std::endl; @@ -73,8 +74,8 @@ void SaveSystem::save(const sf::Vector2f& playerPosition, const int& playerAnima outFile.close(); } -bool SaveSystem::load(sf::Vector2f& playerPosition, int& playerAnimation, - std::vector& npcPositions, std::vector& npcWaypoints, +bool SaveSystem::load(sf::Vector2f& playerPosition, int& playerAnimation, int& playerLevel, int& playerXp, + int& towerDefenseLevel, std::vector& npcPositions, std::vector& npcWaypoints, int& crystals, int& year, int& day, int& hour, int& minute, int& bankBalance, int& hasBorrowActive, int& penalty, int& interest, int& amountToRepay, int& daysToRepayment, int& startYear, int& startDay, int& startHour, int& startMinute, @@ -94,8 +95,14 @@ bool SaveSystem::load(sf::Vector2f& playerPosition, int& playerAnimation, } // Load player position - if (!(inFile >> playerPosition.x >> playerPosition.y >> playerAnimation)) { - std::cerr << "Error reading player position from save file." << std::endl; + if (!(inFile >> playerPosition.x >> playerPosition.y >> playerAnimation >> playerLevel >> playerXp)) { + std::cerr << "Error reading player position and level from save file." << std::endl; + return false; + } + + // Load tower defense level + if (!(inFile >> towerDefenseLevel)) { + std::cerr << "Error reading tower defense level from save file." << std::endl; return false; } @@ -295,7 +302,8 @@ bool SaveSystem::load(sf::Vector2f& playerPosition, int& playerAnimation, bool SaveSystem::loadPartial(std::string saveFile, int& crystals, int& year, int& day, int& hour, int& minute) { sf::Vector2f playerPosition; - int playerAnimation; + int playerAnimation, playerLevel, playerXp; + int towerDefenseLevel; std::vector npcPositions; std::vector npcWaypoints; int bankBalance, penalty, interest, amountToRepay, daysToRepayment, @@ -316,8 +324,8 @@ bool SaveSystem::loadPartial(std::string saveFile, int& crystals, int& year, int std::string tmp = mSaveFilePath; mSaveFilePath = saveFile; - bool success = load(playerPosition, playerAnimation, npcPositions, - npcWaypoints, crystals, year, day, + bool success = load(playerPosition, playerAnimation, playerLevel, playerXp, + towerDefenseLevel, npcPositions, npcWaypoints, crystals, year, day, hour, minute, bankBalance, hasBorrowActive, penalty, interest, amountToRepay, daysToRepayment, startYear, startDay, startHour, startMinute, inventoryItemId, inventoryItemQuantity, diff --git a/src/Rpg/saveSystem/SaveSystem.h b/src/Rpg/saveSystem/SaveSystem.h index 315b80d..4ea8c1a 100644 --- a/src/Rpg/saveSystem/SaveSystem.h +++ b/src/Rpg/saveSystem/SaveSystem.h @@ -9,8 +9,8 @@ class SaveSystem { public: SaveSystem(); - void save(const sf::Vector2f& playerPosition, const int& playerAnimation, - const std::vector& npcPositions, const std::vector& npcWaypoints, + void save(const sf::Vector2f& playerPosition, const int& playerAnimation, const int& playerLevel, const int& playerXp, + const int& towerDefenseLevel, const std::vector& npcPositions, const std::vector& npcWaypoints, const int& crystals, const int& year, const int& day, const int& hour, const int& minute, const int& bankBalance, const int& hasBorrowActive, const int& penalty, const int& interest, const int& amountToRepay, const int& daysToRepayment, @@ -25,8 +25,8 @@ class SaveSystem { const sf::Vector2f& fixedCameraPos, const int& chapter, const std::vector& flagKeys, const std::vector& flagValues); - bool load(sf::Vector2f& playerPosition, int& playerAnimation, - std::vector& npcPositions, std::vector& npcWaypoints, + bool load(sf::Vector2f& playerPosition, int& playerAnimation, int& playerLevel, int& playerXp, + int& towerDefenseLevel, std::vector& npcPositions, std::vector& npcWaypoints, int& crystals, int& year, int& day, int& hour, int& minute, int& bankBalance, int& hasBorrowActive, int& penalty, int& interest, int& amountToRepay, int& daysToRepayment, int& startYear, int& startDay, int& startHour, int& startMinute, diff --git a/src/TowerDefense/gamengine/GameEngine.cpp b/src/TowerDefense/gamengine/GameEngine.cpp index a9926dd..794b849 100644 --- a/src/TowerDefense/gamengine/GameEngine.cpp +++ b/src/TowerDefense/gamengine/GameEngine.cpp @@ -34,7 +34,7 @@ GameEngine::GameEngine(sf::RenderWindow& window, GameManager* gameManager) mShowText2(false), mGameManager(gameManager), mSmallMenu(mWindow, this, gameManager, mCurrentLevel, mAvailableTowers), - mLevelCompleteMenu(mWindow, this, gameManager, mCurrentLevel), + mLevelCompleteMenu(mWindow, this, nullptr, gameManager, mCurrentLevel, true), mGameOverMenu(mWindow, this, gameManager, mCurrentLevel, mCrystals, mAvailableTowers) { if (!mFont.loadFromFile("assets/fonts/gameFont.ttf")) diff --git a/src/TowerDefense/menues/LevelCompleteMenu.cpp b/src/TowerDefense/menues/LevelCompleteMenu.cpp index 94fe925..4589a37 100644 --- a/src/TowerDefense/menues/LevelCompleteMenu.cpp +++ b/src/TowerDefense/menues/LevelCompleteMenu.cpp @@ -1,22 +1,24 @@ #include "LevelCompleteMenu.h" #include "../gamengine/GameEngine.h" +#include "../../Rpg/gamengine/RPGEngine.h" #include "../../GameManager.h" #include "../../Rpg/inventory/items/Wood.h" #include "../../Rpg/inventory/items/TowerBlueprint.h" #include "../../Rpg/inventory/items/TowerBlueprintRare.h" #include "../../Rpg/inventory/items/TowerBlueprintEpic.h" #include "../../Rpg/inventory/items/TowerBlueprintMythic.h" +#include "RewardSystem.h" #include -LevelCompleteMenu::LevelCompleteMenu(sf::RenderWindow& window, GameEngine* game, - GameManager* gameManager, int level) - : mGame(game), mGameManager(gameManager), mLevel(level), - continueButton(sf::Vector2f(0, 0), sf::Vector2f(165, 40), "Continue") { +LevelCompleteMenu::LevelCompleteMenu(sf::RenderWindow& window, GameEngine* towerGame, + RPGEngine* rpgGame, GameManager* gameManager, int level, bool isTowerLevel) + : mTowerGame(towerGame), mRpgGame(rpgGame), mGameManager(gameManager), mLevel(level), mActive(false), + mIsTowerLevel(isTowerLevel), mContinueButton(sf::Vector2f(0, 0), sf::Vector2f(165, 40), "Continue") { if (!mFont.loadFromFile("assets/fonts/gameFont.ttf")) std::cerr << "Failed to load font for AnalyzeMenu!" << std::endl; - mMenuShape.setSize(sf::Vector2f(window.getSize().x / 5.5f, window.getSize().y / 3.f)); + mMenuShape.setSize(sf::Vector2f(window.getSize().x / 5.3f, window.getSize().y / 2.3f)); mMenuShape.setFillColor(sf::Color(50, 50, 50, 255)); mMenuShape.setPosition((window.getSize().x - mMenuShape.getSize().x) / 2, (window.getSize().y - mMenuShape.getSize().y) / 2); @@ -24,42 +26,96 @@ LevelCompleteMenu::LevelCompleteMenu(sf::RenderWindow& window, GameEngine* game, mBackground.setSize(sf::Vector2f(window.getSize().x, window.getSize().y)); mBackground.setFillColor(sf::Color(50, 50, 50, 185)); mBackground.setPosition(sf::Vector2f(0, 0)); - continueButton.setPosition(sf::Vector2f(mMenuShape.getPosition().x + (mMenuShape.getSize().x - continueButton.getSize().x) / 2.f, - mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.1f)); - mReward = RewardSystem::generateReward(level); - continueButton.setCallback([this, game, gameManager]() { - if (mGameManager) { - if (mReward.itemId == 0) - mGameManager->switchToRPG(game->getCrystals() + mReward.quantity); - else - mGameManager->switchToRPG(game->getCrystals()); - } else - std::cerr << "Error: GameManager is nullptr in continueButton callback." << std::endl; - }); + if (isTowerLevel) + mLevelCompleteText.setString("Level completed!"); + else + mLevelCompleteText.setString("Level up!"); + mLevelCompleteText.setFont(mFont); + mLevelCompleteText.setCharacterSize(18); + mLevelCompleteText.setFillColor(sf::Color::White); + mLevelCompleteText.setPosition(sf::Vector2f(mMenuShape.getPosition().x + (mMenuShape.getSize().x - mLevelCompleteText.getLocalBounds().width) / 2.f, + mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.05f)); + + mRewardText.setFont(mFont); + mRewardText.setCharacterSize(13); + mRewardText.setFillColor(sf::Color::White); + + mQuantityText.setFont(mFont); + mQuantityText.setCharacterSize(13); + mQuantityText.setFillColor(sf::Color::White); - mButtons.push_back(continueButton); - mRewardShape.setSize(sf::Vector2f(mMenuShape.getSize().x * 0.6f, mMenuShape.getSize().y * 0.55f)); + mRewardShape.setSize(sf::Vector2f(mMenuShape.getSize().x * 0.63f, mMenuShape.getSize().y * 0.56f)); mRewardShape.setFillColor(sf::Color::Transparent); mRewardShape.setOutlineColor(sf::Color::White); mRewardShape.setOutlineThickness(1.5f); mRewardShape.setPosition(sf::Vector2f(mMenuShape.getPosition().x + (mMenuShape.getSize().x - mRewardShape.getSize().x) / 2.f, - mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.9f - mRewardShape.getSize().y)); + mMenuShape.getPosition().y + mMenuShape.getSize().y * 0.18f)); - mRewardText.setFont(mFont); - mRewardText.setString(mReward.name); - mRewardText.setCharacterSize(13); - mRewardText.setFillColor(sf::Color::White); - mRewardText.setPosition(sf::Vector2f(mRewardShape.getPosition().x +(mRewardShape.getSize().x - mRewardText.getLocalBounds().width) / 2.f, - mRewardShape.getPosition().y + mRewardShape.getSize().y * 0.75f - mRewardText.getLocalBounds().height)); + mContinueButton.setPosition(sf::Vector2f(mMenuShape.getPosition().x + (mMenuShape.getSize().x - mContinueButton.getSize().x) / 2.f, + mRewardShape.getPosition().y + mRewardShape.getSize().y * 1.15f)); - mQuantityText.setFont(mFont); - mQuantityText.setString(std::to_string(mReward.quantity)); - mQuantityText.setCharacterSize(13); - mQuantityText.setFillColor(sf::Color::White); - mQuantityText.setPosition(sf::Vector2f(mRewardShape.getPosition().x +(mRewardShape.getSize().x - mQuantityText.getLocalBounds().width) / 2.f, - mRewardShape.getPosition().y + mRewardShape.getSize().y * 0.98f - mRewardText.getLocalBounds().height - mQuantityText.getLocalBounds().height)); + refresh(); +} + +void LevelCompleteMenu::render(sf::RenderWindow& window) { + if (!mIsTowerLevel && !mActive) + return; + + window.draw(mBackground); + window.draw(mMenuShape); + + window.draw(mLevelCompleteText); + window.draw(mRewardShape); + window.draw(mRewardText); + window.draw(mQuantityText); + window.draw(mItemIcon); + + mContinueButton.render(window); +} + +void LevelCompleteMenu::handleMouseClick(const sf::Vector2f& mousePos) { + if (!mIsTowerLevel && !mActive) + return; + + if (mContinueButton.isMouseOver(mousePos)) + mContinueButton.onClick(); +} + +void LevelCompleteMenu::updateHover(const sf::Vector2f& mousePos) { + if (!mIsTowerLevel && !mActive) + return; + + mContinueButton.updateHover(mousePos); +} + +void LevelCompleteMenu::refresh() { + if (mIsTowerLevel) + mReward = RewardSystem::generateTowerLevelReward(mLevel); + else + mReward = RewardSystem::generateReward(mLevel); + + mContinueButton.setCallback([this]() { + if (mIsTowerLevel) { + if (mGameManager) { + if (mReward.itemId == 0) + mGameManager->switchToRPG(mTowerGame->getCrystals() + mReward.quantity); + else + mGameManager->switchToRPG(mTowerGame->getCrystals()); + + int xp = static_cast(50.f * std::pow(mLevel, 1.3f) * 0.6f); + mGameManager->getGameEngine().addXp(xp); + + mGameManager->getGameEngine().advanceTowerDefenseLevel(); + } else + std::cerr << "Error: GameManager is nullptr in continueButton callback." << std::endl; + } else { + if (mReward.itemId == 0) + mRpgGame->addCrystals(mReward.quantity); + mActive = false; + } + }); if (mReward.itemId) { std::unique_ptr mItem; @@ -76,37 +132,38 @@ LevelCompleteMenu::LevelCompleteMenu(sf::RenderWindow& window, GameEngine* game, if (mItem) { mItemIcon = mItem->getIcon(); - gameManager->getGameEngine().getInventory().addItem(std::move(mItem), mReward.quantity); + mGameManager->getGameEngine().getInventory().addItem(std::move(mItem), mReward.quantity); } } else { mItemIcon.setSize(sf::Vector2f(50.f, 50.f)); mItemIcon.setFillColor(sf::Color(50, 50, 200, 255)); } + + mRewardText.setString(mReward.name); + mRewardText.setPosition(sf::Vector2f(mRewardShape.getPosition().x +(mRewardShape.getSize().x - mRewardText.getLocalBounds().width) / 2.f, + mRewardShape.getPosition().y + mRewardShape.getSize().y * 0.75f - mRewardText.getLocalBounds().height)); + + mQuantityText.setString(std::to_string(mReward.quantity)); + mQuantityText.setPosition(sf::Vector2f(mRewardShape.getPosition().x +(mRewardShape.getSize().x - mQuantityText.getLocalBounds().width) / 2.f, + mRewardShape.getPosition().y + mRewardShape.getSize().y * 0.98f - mRewardText.getLocalBounds().height - mQuantityText.getLocalBounds().height)); + mItemIcon.setPosition(sf::Vector2f(mRewardShape.getPosition().x + (mRewardShape.getSize().x - mItemIcon.getSize().x) / 2.f, - mRewardShape.getPosition().y + mRewardShape.getSize().y * 0.1f)); + mRewardShape.getPosition().y + mRewardShape.getSize().y * 0.2f)); } -void LevelCompleteMenu::render(sf::RenderWindow& window) { - window.draw(mBackground); - window.draw(mMenuShape); - window.draw(mRewardShape); - window.draw(mRewardText); - window.draw(mQuantityText); - window.draw(mItemIcon); +bool LevelCompleteMenu::isActive() const { + return mActive; +} - for (auto& button : mButtons) - button.render(window); +void LevelCompleteMenu::setActive(bool state) { + mActive = state; } -void LevelCompleteMenu::handleMouseClick(const sf::Vector2f& mousePos) { - for (auto& button : mButtons) { - if (button.isMouseOver(mousePos)) - button.onClick(); - } +int LevelCompleteMenu::getLevel() const { + return mLevel; } -void LevelCompleteMenu::updateHover(const sf::Vector2f& mousePos) { - for (auto& button : mButtons) - button.updateHover(mousePos); +void LevelCompleteMenu::setLevel(int level) { + mLevel = level; } diff --git a/src/TowerDefense/menues/LevelCompleteMenu.h b/src/TowerDefense/menues/LevelCompleteMenu.h index 4451270..08aff57 100644 --- a/src/TowerDefense/menues/LevelCompleteMenu.h +++ b/src/TowerDefense/menues/LevelCompleteMenu.h @@ -5,32 +5,44 @@ #include class GameEngine; +class RPGEngine; class GameManager; +// Used for both tower defense level completion and main character level progression class LevelCompleteMenu { public: - LevelCompleteMenu(sf::RenderWindow& window, GameEngine* game, - GameManager* gameManager, int level); + LevelCompleteMenu(sf::RenderWindow& window, GameEngine* towerGame, RPGEngine* rpgGame, + GameManager* gameManager, int level, bool isTowerLevel); void render(sf::RenderWindow& window); void handleMouseClick(const sf::Vector2f& mousePos); void updateHover(const sf::Vector2f& mousePos); + void refresh(); + bool isActive() const; + void setActive(bool state); + + int getLevel() const; + void setLevel(int level); + private: sf::RectangleShape mMenuShape; sf::RectangleShape mBackground; - - std::vector