From c3ff193b46b5a7943a0f0d5ff044d0ac49cfe8d4 Mon Sep 17 00:00:00 2001 From: quinndu0 <160988691+ntut-Tu@users.noreply.github.com> Date: Fri, 24 May 2024 10:51:03 +0800 Subject: [PATCH 1/5] efficacy --- include/Mechanics/UnitManager.hpp | 2 +- src/AI/EnemyScripts.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/Mechanics/UnitManager.hpp b/include/Mechanics/UnitManager.hpp index cbcedc77..6325b463 100644 --- a/include/Mechanics/UnitManager.hpp +++ b/include/Mechanics/UnitManager.hpp @@ -154,7 +154,7 @@ class UnitManager : public Player { auto avatar = std::make_shared(house); avatar->Start(cellPos); // avatar ->setNewDestination(cellPos); - m_AvatarManager->assignMoveOrderToAvatar(avatar,{cellPos.x+1,cellPos.y+1}); +// m_AvatarManager->assignMoveOrderToAvatar(avatar,{cellPos.x+1,cellPos.y+1}); m_AvatarManager->AppendAvatar(avatar); m_troopSize+=1; break; diff --git a/src/AI/EnemyScripts.cpp b/src/AI/EnemyScripts.cpp index 0159d1df..756a3e28 100644 --- a/src/AI/EnemyScripts.cpp +++ b/src/AI/EnemyScripts.cpp @@ -85,8 +85,8 @@ void EnemyScripts::setCDTime(float time,SpawnMode spawnMode,bool cheat){ } if(cheat){ - m_AvatarCDTime*=CHEAT; - m_buildingCDTime*=CHEAT; + m_AvatarCDTime*=0.1; + m_buildingCDTime*=0.1; } } @@ -134,7 +134,7 @@ void EnemyScripts::buildADV(){ } void EnemyScripts::spawnUnit(){ - if(m_selectedAvatarType!=UnitType::NONE||m_EnemyObjectManager->getAvatarCount()>50){ + if(m_selectedAvatarType!=UnitType::NONE||m_EnemyObjectManager->getAvatarCount()>20){ return; } if(m_EnemyObjectManager->getAvatarCount()<=25 && m_EnemyObjectManager->getTotalCurrency()> 100){ From aae88af8362de96480fe3e438224267bc9916a4d Mon Sep 17 00:00:00 2001 From: quinndu0 <160988691+ntut-Tu@users.noreply.github.com> Date: Fri, 31 May 2024 10:19:07 +0800 Subject: [PATCH 2/5] AI Update --- CMakeLists.txt | 1 + include/AI/AIGroupCommander.hpp | 138 ++++++++++++++++++++++- include/AI/EnemyScripts.hpp | 3 +- include/Avatar/Avatar.hpp | 9 +- include/Avatar/Infantry.hpp | 1 - include/Map/Map.hpp | 29 +++++ include/Map/Tile.hpp | 25 ++++ include/Mechanics/AvatarManager.hpp | 7 +- include/Mechanics/BuiltStructure.hpp | 11 ++ include/Mechanics/Player.hpp | 6 +- include/Mechanics/UnitManager.hpp | 32 ++---- include/Scene/SandBoxScene.hpp | 2 - include/Scene/TutorialScene.hpp | 2 - include/Structure/AdvencePowerPlants.hpp | 4 +- src/AI/EnemyScripts.cpp | 18 ++- src/Scene/SandBoxScene.cpp | 9 +- src/Scene/TutorialScene.cpp | 4 +- src/Structure/WarFactory.cpp | 2 +- src/UI/UIScriptProcess.cpp | 2 +- 19 files changed, 258 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c49260d..1b166d34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,7 @@ set(INCLUDE_FILES ${INCLUDE_DIR}/Enemy/Enemy.hpp ${INCLUDE_DIR}/Enemy/EnemyScripts.hpp + ${INCLUDE_DIR}/Enemy/AIGroupCommander.hpp ${INCLUDE_DIR}/Core/Context.hpp ${INCLUDE_DIR}/Core/DebugMessageCallback.hpp diff --git a/include/AI/AIGroupCommander.hpp b/include/AI/AIGroupCommander.hpp index 149667a9..08d300df 100644 --- a/include/AI/AIGroupCommander.hpp +++ b/include/AI/AIGroupCommander.hpp @@ -4,7 +4,143 @@ #ifndef PRACTICALTOOLSFORSIMPLEDESIGN_AIGROUPCOMMANDER_HPP #define PRACTICALTOOLSFORSIMPLEDESIGN_AIGROUPCOMMANDER_HPP +#include "Mechanics/UnitManager.hpp" +#define GROUP_SIZE 4 +#define AUTO_FIND_RANGE 4 +#define AUTO_ATTACK_METHOD 2 +class AIGroupCommander { +private: + std::shared_ptr m_PlayerUnitManager; + std::shared_ptr m_AIUnitManager; + std::shared_ptr m_AIAvatarManager; + std::shared_ptr m_Map; + + std::vector>> m_offensiveGroup; + std::vector> m_defensiveGroup; +public: + AIGroupCommander(std::shared_ptr PlayerUnitManager,std::shared_ptr AIUnitManager,std::shared_ptr Map):m_PlayerUnitManager(PlayerUnitManager),m_AIUnitManager(AIUnitManager),m_Map(Map){}; + ~AIGroupCommander(){}; + void Start(){ + m_AIAvatarManager = m_AIUnitManager->getAvatarManager(); + m_defensiveGroup = m_AIAvatarManager->getAvatarArray(); + } + void Update(){ + updateDefensiveGroup(); + updateOffensiveGroup(); + } + + + void setAllTroopToAttackMode(){ + for(auto i : m_defensiveGroup){ + addTroopToOffensiveGroup(i); + } + m_defensiveGroup.clear(); + } + void setTroopToAttackMode(int num){ + int max = static_cast(m_defensiveGroup.size()); + for(int i=max-1;i>=0 && num>=max-i;i--){ + addTroopToOffensiveGroup(m_defensiveGroup[i]); + m_defensiveGroup.pop_back(); + } + } + + int getDefensiveTroopSize(){ + return static_cast(m_defensiveGroup.size()); + } + + int getOffensiveTroopSize(){ + int totalSize = 0; + for (const auto& row : m_offensiveGroup) { + totalSize += static_cast(row.size()); + } + return totalSize; + } +protected: + void updateOffensiveGroup(){ + for(auto i : m_offensiveGroup){ + for(int j=0;j(i.size());j++){ + if(i[j]->getHealth()->ifDead()){ + i.erase(i.begin()+j); + } + } + } + updateOffensiveTroopAttackTarget(); + } + void updateDefensiveGroup(){ + int t=0; + for(auto i : m_defensiveGroup){ + if(i->getHealth()->ifDead()){ + m_defensiveGroup.erase(m_defensiveGroup.begin()+t); + }else{ + autoAttack(i,AUTO_ATTACK_METHOD); + }; + t++; + } + std::vector> temp = m_AIAvatarManager->getAvatarArray(); + for(int i=static_cast(temp.size());i>=0;i--){ + if(temp[i]->getAIType()==AI_Type::NONE){ + temp[i]->setAIType(AI_Type::DEFENCE); + m_defensiveGroup.push_back(temp[i]); + }else{ + break; + } + } + } + void addTroopToOffensiveGroup(std::shared_ptr unit){ + auto it = std::find_if(m_offensiveGroup.begin(), m_offensiveGroup.end(), [](const std::vector>& group) { + return group.size() < GROUP_SIZE; + }); + unit->setAIType(AI_Type::ATTACK); + if (it != m_offensiveGroup.end()) { + it->push_back(unit); + } else { + m_offensiveGroup.push_back(std::vector>()); + m_offensiveGroup.back().push_back(unit); + } + } + void autoAttack(std::shared_ptr unit,int method){ + switch (method) { + case 1: + for(auto i : m_PlayerUnitManager->getAvatarManager()->getAvatarArray()){ + if(i->getDistance(unit->getCurrentLocationInCell())<=AUTO_FIND_RANGE){ + //attack + m_AIAvatarManager->assignAttackOrderToAvatar(unit,i->getCurrentLocationInCell()); + return; + } + } + break; + case 2: + glm::vec2 targetCell = m_Map->findEnemyInRange(AUTO_FIND_RANGE,unit->getCurrentLocationInCell(),HouseType::ENEMY); + if(targetCell.x == -1 && targetCell.y == -1){ + return; + } + //attack + m_AIAvatarManager->assignAttackOrderToAvatar(unit,targetCell); + break; + } + } + void updateOffensiveTroopAttackTarget(){ + for(auto i : m_offensiveGroup){ + if(i.size()>0){ + if (m_AIAvatarManager->ifAvatarHasNemesis(i.front())){ + // find new target + glm::vec2 targetCell = m_Map->findEnemyInRange( + 100, i.front()->getCurrentLocationInCell(), + HouseType::ENEMY); + if (targetCell.x == -1 && targetCell.y == -1) { + return; + } + // attack + for (auto j : i) { + m_AIAvatarManager->assignAttackOrderToAvatar( + j, targetCell); + } + } + } + } + } +}; + -class AIGroupCommander {}; #endif // PRACTICALTOOLSFORSIMPLEDESIGN_AIGROUPCOMMANDER_HPP diff --git a/include/AI/EnemyScripts.hpp b/include/AI/EnemyScripts.hpp index a419e7e4..2e54ccc0 100644 --- a/include/AI/EnemyScripts.hpp +++ b/include/AI/EnemyScripts.hpp @@ -4,8 +4,8 @@ #ifndef PRACTICALTOOLSFORSIMPLEDESIGN_ENEMYSCRIPTS_HPP #define PRACTICALTOOLSFORSIMPLEDESIGN_ENEMYSCRIPTS_HPP -#include "Enemy.hpp" #include "Mechanics/UnitManager.hpp" +#include "AIGroupCommander.hpp" #define SPACE 4 @@ -15,6 +15,7 @@ class EnemyScripts{ std::shared_ptr m_GameObjectManager; std::shared_ptr m_EnemyObjectManager; std::shared_ptr m_Map; + std::shared_ptr m_AIGroupCommander; glm::vec2 m_baseCell = {20,20}; int constructCountX = 0; diff --git a/include/Avatar/Avatar.hpp b/include/Avatar/Avatar.hpp index 3bc07483..21c96b26 100644 --- a/include/Avatar/Avatar.hpp +++ b/include/Avatar/Avatar.hpp @@ -15,7 +15,7 @@ #include "Selectable.hpp" #include "Unit/Huntable.hpp" #include "Util/Image.hpp" - +enum class AI_Type{NONE,DEFENCE,ATTACK}; class Avatar : public Util::GameObject, public Selectable, public Huntable { public: @@ -60,6 +60,12 @@ class Avatar : public Util::GameObject, public Selectable, public Huntable { void DrawAvatar(); + void setAIType(AI_Type type){ + m_aiType=type; + } + AI_Type getAIType(){ + return m_aiType; + } public: GameObjectID getID() { return m_ID; } @@ -102,5 +108,6 @@ class Avatar : public Util::GameObject, public Selectable, public Huntable { private: GameObjectID m_ID; + AI_Type m_aiType = AI_Type::NONE; }; #endif // PRACTICALTOOLSFORSIMPLEDESIGN_AVATAR_HPP diff --git a/include/Avatar/Infantry.hpp b/include/Avatar/Infantry.hpp index c1b7bf7f..8885c364 100644 --- a/include/Avatar/Infantry.hpp +++ b/include/Avatar/Infantry.hpp @@ -19,7 +19,6 @@ class Infantry : public Avatar { // setHp(50); getMoving()->setMovementSpeed(4); } - private: }; #endif // PRACTICALTOOLSFORSIMPLEDESIGN_INFANTRY_HPP diff --git a/include/Map/Map.hpp b/include/Map/Map.hpp index 036f9400..b6cff4b2 100644 --- a/include/Map/Map.hpp +++ b/include/Map/Map.hpp @@ -55,6 +55,35 @@ class MapClass : public Core::Drawable { getTileByCellPosition(position)->removeStructure(); } + glm::vec2 findEnemyInRange(int attackRange,glm::vec2 myCell,HouseType myHouse){ + glm::vec2 NullPos={-1,-1}; + int x,y=1; + int r=1; + for(r=1;rifEnemyAtTile(myHouse)){ + return {myCell.x+x,myCell.y+y}; + } + } + for(y=r-1;y>=-1*r;y--){ + if(getTileByCellPosition({myCell.x+x,myCell.y+y})->ifEnemyAtTile(myHouse)){ + return {myCell.x+x,myCell.y+y}; + } + } + for(x=r-1;x>-1*r;x--){ + if(getTileByCellPosition({myCell.x+x,myCell.y+y})->ifEnemyAtTile(myHouse)){ + return {myCell.x+x,myCell.y+y}; + } + } + for(y=-1*r+1;yifEnemyAtTile(myHouse)){ + return {myCell.x+x,myCell.y+y}; + } + } + } + return NullPos; + } protected: void InitGrid(); diff --git a/include/Map/Tile.hpp b/include/Map/Tile.hpp index 098558d0..2ab99fcb 100644 --- a/include/Map/Tile.hpp +++ b/include/Map/Tile.hpp @@ -117,6 +117,31 @@ class TileClass { return false; } + bool ifEnemyAtTile(HouseType myHouse) { + if(myHouse==HouseType::MY){ + if (m_Structure->getID().getHouse() == HouseType::ENEMY) { + return true; + } + for (auto a : m_Avatars) { + if (a->getID().getHouse() == HouseType::ENEMY) { + return true; + } + } + return false; + }else if(myHouse==HouseType::ENEMY){ + if (m_Structure->getID().getHouse() == HouseType::MY) { + return true; + } + for (auto a : m_Avatars) { + if (a->getID().getHouse() == HouseType::MY) { + return true; + } + } + return false; + } + } + + private: bool m_TerrainBuildable; bool m_TerrainWalkable; diff --git a/include/Mechanics/AvatarManager.hpp b/include/Mechanics/AvatarManager.hpp index dd3cd4a9..49fc5a7a 100644 --- a/include/Mechanics/AvatarManager.hpp +++ b/include/Mechanics/AvatarManager.hpp @@ -35,7 +35,12 @@ class AvatarManager { void assignAttackOrderToAvatar(std::shared_ptr unit, glm::vec2 destcell); - + int getAvatarSize(){ + return static_cast(m_AvatarArray.size()); + } + bool ifAvatarHasNemesis(std::shared_ptr unit){ + return m_NemesisManager->ifAvatarHasNemesis(unit); + } protected: void assignOrderToMyAvatar(std::shared_ptr unit); void updateTileWhileAvatarMoving(std::shared_ptr unit); diff --git a/include/Mechanics/BuiltStructure.hpp b/include/Mechanics/BuiltStructure.hpp index 6c39605e..b8a11119 100644 --- a/include/Mechanics/BuiltStructure.hpp +++ b/include/Mechanics/BuiltStructure.hpp @@ -84,6 +84,17 @@ class BuiltStructure { m_PlayerWayPointCell =MapUtil::GlobalCoordToCellCoord( std::dynamic_pointer_cast(i) ->GetWayPointLocation()); + int count = 0; + int offsetX = 1,offsetY=1; + while(m_Map->getTileByCellPosition(m_PlayerWayPointCell)->getAvatars().size()>=4){ + offsetX = (rand() % 7*(count/5)) - 3*(count/5); + offsetY = (rand() % 7*(count/5)) - 3*(count/5); + count++; + std::dynamic_pointer_cast(i)->SetWayPointLocationByCellCoord({m_PlayerWayPointCell.x+offsetX,m_PlayerWayPointCell.y+offsetY}); + m_PlayerWayPointCell =MapUtil::GlobalCoordToCellCoord( + std::dynamic_pointer_cast(i) + ->GetWayPointLocation()); + } } } } diff --git a/include/Mechanics/Player.hpp b/include/Mechanics/Player.hpp index f662ac10..32d7894f 100644 --- a/include/Mechanics/Player.hpp +++ b/include/Mechanics/Player.hpp @@ -16,16 +16,14 @@ class Player { void addFixedPower(int value) { m_FixedPower += value; } int getTotalCurrency() { return m_TotalCurrency; } - int getMaxTroopSize() { return m_MaxTroopSize; } + protected: int getTotalPower(std::vector> m_BuiltStructure) { int totalPower = 0; for (int i = 0; i < m_BuiltStructure.size(); i++) { - if(m_BuiltStructure[i]->getHouseType()==HouseType::MY){ - totalPower += m_BuiltStructure[i]->getElectricPower(); - } + totalPower += m_BuiltStructure[i]->getElectricPower(); } return totalPower; } diff --git a/include/Mechanics/UnitManager.hpp b/include/Mechanics/UnitManager.hpp index 6325b463..277a2a97 100644 --- a/include/Mechanics/UnitManager.hpp +++ b/include/Mechanics/UnitManager.hpp @@ -74,13 +74,6 @@ class UnitManager : public Player { void spawn(std::shared_ptr m_Map, UnitType unit, HouseType house) { - - if (house == HouseType::ENEMY) { - // m_Enemy->addUnitConstructCount(unit, 1); - } else { - // m_Player->setUnitConstructCount(unit, 1); - } - switch (unit) { case UnitType::INFANTRY: { auto avatar = std::make_shared(house); @@ -90,14 +83,12 @@ class UnitManager : public Player { .x == -1) { return; } - avatar->Start(m_StructureManager->getStructureArray() ->getPlayerBarrackCell()); m_AvatarManager->assignMoveOrderToAvatar(avatar,{m_StructureManager->getStructureArray()->getPlayerWayPointCell()}); m_AvatarManager->AppendAvatar(avatar); - m_troopSize+=1; + addUnitConstructCount(unit,1); } - default: { printf("(GOM)error! try to spawn unknown type\n"); break; @@ -112,9 +103,9 @@ class UnitManager : public Player { auto structure = std::make_shared(house); auto globalPos = MapUtil::CellCoordToGlobal(cellPos); structure->Start(globalPos); - structure->SetWayPointLocationByCellCoord({cellPos.x+2,cellPos.y-2}); m_StructureManager->getStructureArray()->buildNewStructure( structure, true); + structure->SetWayPointLocationByCellCoord({cellPos.x+2,cellPos.y+2}); break; } case UnitType::ORE_REF: { @@ -153,10 +144,7 @@ class UnitManager : public Player { case UnitType::INFANTRY: { auto avatar = std::make_shared(house); avatar->Start(cellPos); - // avatar ->setNewDestination(cellPos); -// m_AvatarManager->assignMoveOrderToAvatar(avatar,{cellPos.x+1,cellPos.y+1}); m_AvatarManager->AppendAvatar(avatar); - m_troopSize+=1; break; } case UnitType::NONE: { @@ -168,6 +156,9 @@ class UnitManager : public Player { break; } } + if(unit!=UnitType::NONE){ + addUnitConstructCount(unit,1); + } } void addUnitConstructCount(UnitType type, int value) { @@ -177,14 +168,14 @@ class UnitManager : public Player { return unitCount[type]; } int getAvatarCount(){ - return unitCount[UnitType::INFANTRY]; - } - void addAvatarCount(UnitType type,int value){ - unitCount[type] += value; + val = m_AvatarManager->getAvatarSize(); + return val; } + + private: - std::unordered_map unitCount; + std::unordered_map unitCount; std::shared_ptr m_CursorSelection = std::make_shared(); std::shared_ptr m_StructureManager = @@ -194,7 +185,8 @@ class UnitManager : public Player { std::shared_ptr m_Map = std::make_shared(); std::chrono::high_resolution_clock::time_point m_StartTime; double m_lastElapsed = 0.F; - int m_troopSize = 0; + + int val=0; }; #endif // PRACTICALTOOLSFORSIMPLEDESIGN_UNITMANAGER_HPP diff --git a/include/Scene/SandBoxScene.hpp b/include/Scene/SandBoxScene.hpp index 40c74675..255f9ed1 100644 --- a/include/Scene/SandBoxScene.hpp +++ b/include/Scene/SandBoxScene.hpp @@ -28,8 +28,6 @@ class SandBoxScene : public Scene { SpriteSheet m_SpriteSheet; std::shared_ptr m_Cursor = std::make_shared(); Grid testGrid; - std::shared_ptr m_Enemy = - std::make_shared(SceneMode::TUTORIAL); std::shared_ptr m_EnemyScripts = std::make_shared(); Stages m_stage = Stages::START; diff --git a/include/Scene/TutorialScene.hpp b/include/Scene/TutorialScene.hpp index 071f0fa9..894f5311 100644 --- a/include/Scene/TutorialScene.hpp +++ b/include/Scene/TutorialScene.hpp @@ -29,8 +29,6 @@ class TutorialScene : public Scene { SpriteSheet m_SpriteSheet; std::shared_ptr m_Cursor = std::make_shared(); Grid testGrid; - std::shared_ptr m_Enemy = - std::make_shared(SceneMode::TUTORIAL); std::shared_ptr m_EnemyScripts = std::make_shared(); std::shared_ptr m_Text = std::make_shared(); diff --git a/include/Structure/AdvencePowerPlants.hpp b/include/Structure/AdvencePowerPlants.hpp index aa867bd7..7720bce6 100644 --- a/include/Structure/AdvencePowerPlants.hpp +++ b/include/Structure/AdvencePowerPlants.hpp @@ -22,8 +22,8 @@ class ADVPowerPlants : public Structure { "../assets/sprites/ADVPowerPlants_SpriteSheet.png", 72, 72, 13, 0); m_SpriteSheetAnimation->initSpriteSheetAnimation(m_StructureSpriteSheet, false, INTERVAL, false); - m_RelativeOccupiedArea = {{0, 0}, {0, 1}, {0, 2}, - {1, 0}, {1, 1}, {1, 2}}; + m_RelativeOccupiedArea = {{0, 0}, {0, 1}, + {1, 0}, {1, 1},{2,0},{2,1}}; } void SetObjectLocation(glm::vec2 location) override { location = MapUtil::PositionStickToGrid(location); diff --git a/src/AI/EnemyScripts.cpp b/src/AI/EnemyScripts.cpp index 756a3e28..3932372e 100644 --- a/src/AI/EnemyScripts.cpp +++ b/src/AI/EnemyScripts.cpp @@ -2,11 +2,14 @@ // Created by nudle on 2024/5/23. // #include "AI/EnemyScripts.hpp" + +#define MAX_TROOPS_SIZE 25 void EnemyScripts::Start(std::shared_ptr GameObjectManager,std::shared_ptr EnemyObjectManager,std::shared_ptr map,bool active){ m_GameObjectManager=GameObjectManager; m_EnemyObjectManager = EnemyObjectManager; m_Map=map; m_active = active; + m_AIGroupCommander = std::make_shared(GameObjectManager,EnemyObjectManager,map); } void EnemyScripts::Update(){ @@ -39,6 +42,7 @@ void EnemyScripts::Update(){ m_EnemyObjectManager->addTotalCurrency(m_avatarCost/m_AvatarCDTime*(-1.f)); } modeUpdate(); + m_AIGroupCommander->Update(); } } @@ -53,14 +57,20 @@ void EnemyScripts::modeUpdate(){ }else{ if(m_GameObjectManager->getAvatarCount()/m_EnemyObjectManager->getAvatarCount()<=0.5){ //Attack , set all troop to attack mode , set defensive Troop = 0 - updateAllTroopStates(); + //updateAllTroopStates(); + m_AIGroupCommander->setAllTroopToAttackMode(); }else{ //Safe now , build adv or spawn troop - if(!ifBuiltADV()){ + if(m_AIGroupCommander->getDefensiveTroopSize()>25){ + m_AIGroupCommander->setTroopToAttackMode(m_AIGroupCommander->getDefensiveTroopSize()-25); + } + if(!ifBuiltADV() && m_EnemyObjectManager->getAvatarCount()getAvatarCount()getAvatarCount()>20){ + if(m_selectedAvatarType!=UnitType::NONE){ return; } if(m_EnemyObjectManager->getAvatarCount()<=25 && m_EnemyObjectManager->getTotalCurrency()> 100){ diff --git a/src/Scene/SandBoxScene.cpp b/src/Scene/SandBoxScene.cpp index f8974107..fd771b00 100644 --- a/src/Scene/SandBoxScene.cpp +++ b/src/Scene/SandBoxScene.cpp @@ -107,9 +107,10 @@ void SandBoxScene::stageStart() { break; } case Stages::STAGE4: { - for(int i=0;i<50;i++){ - m_EnemyObjectManager->spawn(m_Map, UnitType::INFANTRY, HouseType::ENEMY, - {30+i/5, 5+i%5}); + m_GameObjectManager->spawn(m_Map, UnitType::BARRACKS, HouseType::MY,{5,5}); + + for(int i=0;i<30;i++){ + m_EnemyObjectManager->spawn(m_Map, UnitType::INFANTRY, HouseType::ENEMY); } m_stage = Stages::END; break; @@ -140,6 +141,6 @@ void SandBoxScene::stageUpdate() { } } if (Util::Input::IsKeyPressed(Util::Keycode::DEBUG_KEY )) { - m_Enemy->addTotalCurrency(500); + m_EnemyObjectManager->addTotalCurrency(500); } } diff --git a/src/Scene/TutorialScene.cpp b/src/Scene/TutorialScene.cpp index 12cd17f3..24b863e5 100644 --- a/src/Scene/TutorialScene.cpp +++ b/src/Scene/TutorialScene.cpp @@ -9,9 +9,9 @@ void TutorialScene::Start() { m_Map->Init(100, 100); m_GameObjectManager->Start(m_Map); m_EnemyObjectManager->Start(m_Map); + m_GameObjectManager->setTotalCurrency(5000); + m_EnemyObjectManager->setTotalCurrency(5000); m_UI.Start(m_Map, m_GameObjectManager); - m_Player->setTotalCurrency(5000); - m_Enemy->setTotalCurrency(5000); m_SceneCamera->Start(MapUtil::CellCoordToGlobal(glm::vec2(-10, -10)), MapUtil::CellCoordToGlobal(glm::vec2(100, 100))); diff --git a/src/Structure/WarFactory.cpp b/src/Structure/WarFactory.cpp index 2e7f32fd..bb60cb73 100644 --- a/src/Structure/WarFactory.cpp +++ b/src/Structure/WarFactory.cpp @@ -26,7 +26,7 @@ void WarFactory::Start(glm::vec2 location) { // Set Texture---------------------------------------- m_StructureSpriteSheet->Start( "../assets/sprites/WarFactory_SpriteSheet.png", 72, 48, 15, 0); - SetRelativeOccupiedArea({{0, 0}, {0, 1}, {0, 2}, {1, 0}, {1, 1}, {1, 2}}); + SetRelativeOccupiedArea({{0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 1}, {2, 0}}); m_wayPoint->SetDrawable( std::make_unique("../assets/sprites/flagB.png")); m_HighLight.SetDrawable( diff --git a/src/UI/UIScriptProcess.cpp b/src/UI/UIScriptProcess.cpp index ca33469d..be8c0c00 100644 --- a/src/UI/UIScriptProcess.cpp +++ b/src/UI/UIScriptProcess.cpp @@ -229,7 +229,7 @@ std::shared_ptr UIScriptProcess::spawnAvatar() { // printf("(UISC)spawnAvatar\n"); switch (m_currentInfType) { case UnitType::INFANTRY: { - return std::make_unique(); + return std::make_unique(HouseType::MY); } } } From a353c2157a9073a74c9e46510603fb62519627c7 Mon Sep 17 00:00:00 2001 From: quinndu0 <160988691+ntut-Tu@users.noreply.github.com> Date: Fri, 31 May 2024 11:41:20 +0800 Subject: [PATCH 3/5] update --- include/AI/AIGroupCommander.hpp | 20 ++++++++++++----- include/Mechanics/AvatarManager.hpp | 2 ++ include/Mechanics/UnitManager.hpp | 5 +---- src/AI/EnemyScripts.cpp | 18 +++++++++------ src/Mechanics/AvatarManager.cpp | 14 ++++++++++++ src/Mechanics/UnitManager.cpp | 34 +++++++++++++---------------- src/Scene/SandBoxScene.cpp | 6 ++--- src/Scene/TutorialScene.cpp | 2 +- 8 files changed, 62 insertions(+), 39 deletions(-) diff --git a/include/AI/AIGroupCommander.hpp b/include/AI/AIGroupCommander.hpp index 08d300df..4babeb30 100644 --- a/include/AI/AIGroupCommander.hpp +++ b/include/AI/AIGroupCommander.hpp @@ -31,12 +31,18 @@ class AIGroupCommander { void setAllTroopToAttackMode(){ + if(m_defensiveGroup.empty()){ + return; + } for(auto i : m_defensiveGroup){ addTroopToOffensiveGroup(i); } m_defensiveGroup.clear(); } void setTroopToAttackMode(int num){ + if(m_defensiveGroup.empty()){ + return; + } int max = static_cast(m_defensiveGroup.size()); for(int i=max-1;i>=0 && num>=max-i;i--){ addTroopToOffensiveGroup(m_defensiveGroup[i]); @@ -77,7 +83,7 @@ class AIGroupCommander { t++; } std::vector> temp = m_AIAvatarManager->getAvatarArray(); - for(int i=static_cast(temp.size());i>=0;i--){ + for(int i=static_cast(temp.size())-1;i>=0;i--){ if(temp[i]->getAIType()==AI_Type::NONE){ temp[i]->setAIType(AI_Type::DEFENCE); m_defensiveGroup.push_back(temp[i]); @@ -104,7 +110,7 @@ class AIGroupCommander { for(auto i : m_PlayerUnitManager->getAvatarManager()->getAvatarArray()){ if(i->getDistance(unit->getCurrentLocationInCell())<=AUTO_FIND_RANGE){ //attack - m_AIAvatarManager->assignAttackOrderToAvatar(unit,i->getCurrentLocationInCell()); + m_AIAvatarManager->assignAttackOrderToAvatar(unit,i->getCurrentLocationInCell(),HouseType::ENEMY); return; } } @@ -115,15 +121,18 @@ class AIGroupCommander { return; } //attack - m_AIAvatarManager->assignAttackOrderToAvatar(unit,targetCell); + m_AIAvatarManager->assignAttackOrderToAvatar(unit,targetCell,HouseType::ENEMY); break; } } void updateOffensiveTroopAttackTarget(){ for(auto i : m_offensiveGroup){ if(i.size()>0){ - if (m_AIAvatarManager->ifAvatarHasNemesis(i.front())){ + if (!m_AIAvatarManager->ifAvatarHasNemesis(i.front())){ // find new target + if(m_PlayerUnitManager->getAvatarCount()==0){ + return; + } glm::vec2 targetCell = m_Map->findEnemyInRange( 100, i.front()->getCurrentLocationInCell(), HouseType::ENEMY); @@ -132,8 +141,9 @@ class AIGroupCommander { } // attack for (auto j : i) { + m_AIAvatarManager->assignMoveOrderToAvatar(j,targetCell); m_AIAvatarManager->assignAttackOrderToAvatar( - j, targetCell); + j, targetCell,HouseType::ENEMY); } } } diff --git a/include/Mechanics/AvatarManager.hpp b/include/Mechanics/AvatarManager.hpp index 49fc5a7a..c210a883 100644 --- a/include/Mechanics/AvatarManager.hpp +++ b/include/Mechanics/AvatarManager.hpp @@ -35,6 +35,8 @@ class AvatarManager { void assignAttackOrderToAvatar(std::shared_ptr unit, glm::vec2 destcell); + void assignAttackOrderToAvatar(std::shared_ptr avatar, + glm::vec2 destcell,HouseType myHouse); int getAvatarSize(){ return static_cast(m_AvatarArray.size()); } diff --git a/include/Mechanics/UnitManager.hpp b/include/Mechanics/UnitManager.hpp index 538ba5dd..62abd91c 100644 --- a/include/Mechanics/UnitManager.hpp +++ b/include/Mechanics/UnitManager.hpp @@ -63,8 +63,7 @@ class UnitManager : public Player { return unitCount[type]; } int getAvatarCount(){ - val = m_AvatarManager->getAvatarSize(); - return val; + return m_AvatarManager->getAvatarSize();; } @@ -82,8 +81,6 @@ class UnitManager : public Player { std::shared_ptr m_Map = std::make_shared(); std::chrono::high_resolution_clock::time_point m_StartTime; double m_lastElapsed = 0.F; - - int val=0; }; #endif // PRACTICALTOOLSFORSIMPLEDESIGN_UNITMANAGER_HPP diff --git a/src/AI/EnemyScripts.cpp b/src/AI/EnemyScripts.cpp index 8f0346c4..c1acf7bc 100644 --- a/src/AI/EnemyScripts.cpp +++ b/src/AI/EnemyScripts.cpp @@ -11,6 +11,7 @@ void EnemyScripts::Start(std::shared_ptr GameObjectManager,std::sha m_Map = map; m_active = active; m_AIGroupCommander = std::make_shared(GameObjectManager,EnemyObjectManager,map); + m_AIGroupCommander->Start(); } void EnemyScripts::Update() { @@ -53,27 +54,30 @@ void EnemyScripts::modeUpdate() { if (!ifBuiltBasic()) { buildBasic(); } else { - if (m_EnemyObjectManager->getAvatarCount() == 0 || - (m_GameObjectManager->getAvatarCount() / - m_EnemyObjectManager->getAvatarCount() >= + float playerAvatarCount = m_GameObjectManager->getAvatarCount(); + float enemyAvatarCount = m_EnemyObjectManager->getAvatarCount(); + if (enemyAvatarCount == 0 || + (playerAvatarCount / + enemyAvatarCount >= 2 && - m_GameObjectManager->getAvatarCount() != 0)) { + playerAvatarCount != 0)) { // Defense mode , spawn Troop only spawnUnit(); }else{ - if(m_GameObjectManager->getAvatarCount()/m_EnemyObjectManager->getAvatarCount()<=0.5){ + if(playerAvatarCount/enemyAvatarCount<=0.5){ //Attack , set all troop to attack mode , set defensive Troop = 0 //updateAllTroopStates(); m_AIGroupCommander->setAllTroopToAttackMode(); + spawnUnit(); }else{ //Safe now , build adv or spawn troop if(m_AIGroupCommander->getDefensiveTroopSize()>25){ m_AIGroupCommander->setTroopToAttackMode(m_AIGroupCommander->getDefensiveTroopSize()-25); } - if(!ifBuiltADV() && m_EnemyObjectManager->getAvatarCount()getAvatarCount() avatar, } } } +void AvatarManager::assignAttackOrderToAvatar(std::shared_ptr avatar, + glm::vec2 destcell,HouseType myHouse) { + m_NemesisManager->removeNemesis(avatar); + if (m_Map->getTileByCellPosition(destcell)->ifEnemyAtTile(myHouse)) { + if (m_Map->getTileByCellPosition(destcell)->ifStructureExists()) { + m_NemesisManager->addNemesis( + avatar, m_Map->getTileByCellPosition(destcell)->getStructure()); + } else { + m_NemesisManager->addNemesis( + avatar, + m_Map->getTileByCellPosition(destcell)->getAvatars()[0]); + } + } +} void AvatarManager::assignOrderToMyAvatar(std::shared_ptr avatar) { if (avatar->getID().getHouseType() == HouseType::MY) { diff --git a/src/Mechanics/UnitManager.cpp b/src/Mechanics/UnitManager.cpp index a2c3a32a..0e3fab7e 100644 --- a/src/Mechanics/UnitManager.cpp +++ b/src/Mechanics/UnitManager.cpp @@ -25,7 +25,6 @@ void UnitManager::spawnToWayPoint(UnitType unit, HouseType house) { avatar, m_StructureManager->getStructureArray() ->getPlayerBarrackWayPointCell()); m_AvatarManager->AppendAvatar(avatar); - m_troopSize += 1; } default: { @@ -42,54 +41,48 @@ void UnitManager::spawn(UnitType unit, HouseType house, glm::vec2 cellPos) { auto structure = std::make_shared(house); auto globalPos = MapUtil::CellCoordToGlobal(cellPos); structure->Start(globalPos); - structure->setWaypointLocationByCellCoord( - {cellPos.x + 2, cellPos.y - 2}); - m_StructureManager->getStructureArray()->buildNewStructure(structure, - true); + m_StructureManager->getStructureArray()->buildNewStructure( + structure, true); + structure->setWaypointLocationByCellCoord({cellPos.x+2,cellPos.y+2}); break; } case UnitType::ORE_REF: { auto structure = std::make_shared(house); auto globalPos = MapUtil::CellCoordToGlobal(cellPos); structure->Start(globalPos); - m_StructureManager->getStructureArray()->buildNewStructure(structure, - true); + m_StructureManager->getStructureArray()->buildNewStructure( + structure, true); break; } case UnitType::POWER_PLANT: { auto structure = std::make_shared(house); auto globalPos = MapUtil::CellCoordToGlobal(cellPos); structure->Start(globalPos); - m_StructureManager->getStructureArray()->buildNewStructure(structure, - true); + m_StructureManager->getStructureArray()->buildNewStructure( + structure, true); break; } case UnitType::WAR_FACT: { auto structure = std::make_shared(house); auto globalPos = MapUtil::CellCoordToGlobal(cellPos); structure->Start(globalPos); - structure->setWaypointLocationByCellCoord( - {cellPos.x + 2, cellPos.y - 2}); - m_StructureManager->getStructureArray()->buildNewStructure(structure, - true); + structure->setWaypointLocationByCellCoord({cellPos.x+2,cellPos.y-2}); + m_StructureManager->getStructureArray()->buildNewStructure( + structure, true); break; } case UnitType::ADV_POWER_PLANT: { auto structure = std::make_shared(house); auto globalPos = MapUtil::CellCoordToGlobal(cellPos); structure->Start(globalPos); - m_StructureManager->getStructureArray()->buildNewStructure(structure, - true); + m_StructureManager->getStructureArray()->buildNewStructure( + structure, true); break; } case UnitType::INFANTRY: { auto avatar = std::make_shared(house); avatar->Start(cellPos); - // avatar ->setNewDestination(cellPos); - m_AvatarManager->assignMoveOrderToAvatar( - avatar, {cellPos.x + 1, cellPos.y + 1}); m_AvatarManager->AppendAvatar(avatar); - m_troopSize += 1; break; } case UnitType::NONE: { @@ -101,6 +94,9 @@ void UnitManager::spawn(UnitType unit, HouseType house, glm::vec2 cellPos) { break; } } + if(unit!=UnitType::NONE){ + addUnitConstructCount(unit,1); + } } void UnitManager::Update() { diff --git a/src/Scene/SandBoxScene.cpp b/src/Scene/SandBoxScene.cpp index 67245ac4..9a780bf1 100644 --- a/src/Scene/SandBoxScene.cpp +++ b/src/Scene/SandBoxScene.cpp @@ -101,9 +101,9 @@ void SandBoxScene::stageStart() { break; } case Stages::STAGE4: { - m_GameObjectManager->spawn(m_Map, UnitType::BARRACKS, HouseType::MY,{5,5}); + m_GameObjectManager->spawn( UnitType::BARRACKS, HouseType::MY,{5,5}); for(int i=0;i<30;i++){ - m_EnemyObjectManager->spawn(m_Map, UnitType::INFANTRY, HouseType::ENEMY); + m_EnemyObjectManager->spawn(UnitType::INFANTRY, HouseType::MY,{10,10}); } m_stage = Stages::END; break; @@ -133,7 +133,7 @@ void SandBoxScene::stageUpdate() { if (Util::Input::IsKeyPressed(Util::Keycode::NUM_4)) { m_stage = Stages::STAGE4; m_EnemyScripts->Start(m_GameObjectManager, m_EnemyObjectManager, - m_Map, false); + m_Map, true); stageStart(); } } diff --git a/src/Scene/TutorialScene.cpp b/src/Scene/TutorialScene.cpp index 3368420e..8989413c 100644 --- a/src/Scene/TutorialScene.cpp +++ b/src/Scene/TutorialScene.cpp @@ -11,7 +11,7 @@ void TutorialScene::Start() { m_EnemyObjectManager->Start(m_Map); m_GameObjectManager->setTotalCurrency(5000); m_EnemyObjectManager->setTotalCurrency(5000); - m_UI.Start(m_Map, m_GameObjectManager); + m_UI->Start(m_Map, m_GameObjectManager); m_SceneCamera->Start(MapUtil::CellCoordToGlobal(glm::vec2(-10, -10)), MapUtil::CellCoordToGlobal(glm::vec2(100, 100))); From 432f6de5339678add5a35a7ccb5ce235c191e2ed Mon Sep 17 00:00:00 2001 From: quinndu0 <160988691+ntut-Tu@users.noreply.github.com> Date: Fri, 31 May 2024 11:50:27 +0800 Subject: [PATCH 4/5] update --- src/AI/EnemyScripts.cpp | 4 ++-- src/Scene/SandBoxScene.cpp | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/AI/EnemyScripts.cpp b/src/AI/EnemyScripts.cpp index c1acf7bc..4d0d49cf 100644 --- a/src/AI/EnemyScripts.cpp +++ b/src/AI/EnemyScripts.cpp @@ -186,7 +186,7 @@ void EnemyScripts::UpdateSpawnScript(SpawnMode spawnMode) { if (m_selectedBuildingType == UnitType::NONE) { return; } - m_GameObjectManager->spawn( + m_EnemyObjectManager->spawn( m_selectedBuildingType, HouseType::ENEMY, {m_baseCell.x + constructCountX, m_baseCell.y + constructCountY}); m_EnemyObjectManager->addUnitConstructCount(m_selectedBuildingType, 1); @@ -206,7 +206,7 @@ void EnemyScripts::UpdateSpawnScript(SpawnMode spawnMode) { return; } if (m_selectedAvatarType == UnitType::INFANTRY) { - m_GameObjectManager->spawnToWayPoint(m_selectedAvatarType, + m_EnemyObjectManager->spawnToWayPoint(m_selectedAvatarType, HouseType::ENEMY); setCost(0, SpawnMode::AVATAR); setCDTime(0.f, SpawnMode::AVATAR); diff --git a/src/Scene/SandBoxScene.cpp b/src/Scene/SandBoxScene.cpp index 9a780bf1..3c69bcd5 100644 --- a/src/Scene/SandBoxScene.cpp +++ b/src/Scene/SandBoxScene.cpp @@ -102,9 +102,8 @@ void SandBoxScene::stageStart() { } case Stages::STAGE4: { m_GameObjectManager->spawn( UnitType::BARRACKS, HouseType::MY,{5,5}); - for(int i=0;i<30;i++){ - m_EnemyObjectManager->spawn(UnitType::INFANTRY, HouseType::MY,{10,10}); - } + m_GameObjectManager->spawn(UnitType::INFANTRY, HouseType::MY, {5, 7}); + m_GameObjectManager->spawn(UnitType::INFANTRY, HouseType::MY, {5, 6}); m_stage = Stages::END; break; } From f66ad2610275823600f70f9e779a8e4836426efd Mon Sep 17 00:00:00 2001 From: quinndu0 <160988691+ntut-Tu@users.noreply.github.com> Date: Fri, 31 May 2024 12:14:27 +0800 Subject: [PATCH 5/5] update --- include/AI/AIGroupCommander.hpp | 21 ++++++++++----------- src/AI/EnemyScripts.cpp | 1 - 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/AI/AIGroupCommander.hpp b/include/AI/AIGroupCommander.hpp index 4babeb30..a81383ff 100644 --- a/include/AI/AIGroupCommander.hpp +++ b/include/AI/AIGroupCommander.hpp @@ -73,22 +73,18 @@ class AIGroupCommander { updateOffensiveTroopAttackTarget(); } void updateDefensiveGroup(){ - int t=0; - for(auto i : m_defensiveGroup){ - if(i->getHealth()->ifDead()){ - m_defensiveGroup.erase(m_defensiveGroup.begin()+t); + for(int i = static_cast(m_defensiveGroup.size());i>0;--i ){ + if(m_defensiveGroup[i-1]->getHealth()->ifDead()){ + m_defensiveGroup.erase(m_defensiveGroup.begin()+i-1); }else{ - autoAttack(i,AUTO_ATTACK_METHOD); + autoAttack(m_defensiveGroup[i-1],AUTO_ATTACK_METHOD); }; - t++; } std::vector> temp = m_AIAvatarManager->getAvatarArray(); for(int i=static_cast(temp.size())-1;i>=0;i--){ if(temp[i]->getAIType()==AI_Type::NONE){ temp[i]->setAIType(AI_Type::DEFENCE); m_defensiveGroup.push_back(temp[i]); - }else{ - break; } } } @@ -140,10 +136,13 @@ class AIGroupCommander { return; } // attack - for (auto j : i) { - m_AIAvatarManager->assignMoveOrderToAvatar(j,targetCell); + for (int j=static_cast(i.size());j>0;--j) { + if(i[j-1]->getHealth()->ifDead()){ + i.erase(i.begin()+j-1); + } + m_AIAvatarManager->assignMoveOrderToAvatar(i[j-1],targetCell); m_AIAvatarManager->assignAttackOrderToAvatar( - j, targetCell,HouseType::ENEMY); + i[j-1], targetCell,HouseType::ENEMY); } } } diff --git a/src/AI/EnemyScripts.cpp b/src/AI/EnemyScripts.cpp index 4d0d49cf..a4a44bb7 100644 --- a/src/AI/EnemyScripts.cpp +++ b/src/AI/EnemyScripts.cpp @@ -78,7 +78,6 @@ void EnemyScripts::modeUpdate() { buildADV(); spawnUnit(); }else if(enemyAvatarCount