Skip to content

Commit

Permalink
Merge pull request #3 from ntut-Tu/AICommader_Update
Browse files Browse the repository at this point in the history
Ai commader update
  • Loading branch information
ntut-Tu authored May 31, 2024
2 parents 3c3a82b + f66ad26 commit 1b9c348
Show file tree
Hide file tree
Showing 20 changed files with 312 additions and 73 deletions.
7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,11 @@ set(INCLUDE_FILES
${INCLUDE_DIR}/Scene/SandBoxScene.hpp


${INCLUDE_DIR}/AI/Enemy.hpp
${INCLUDE_DIR}/AI/EnemyScripts.hpp

${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
Expand Down
147 changes: 146 additions & 1 deletion include/AI/AIGroupCommander.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,152 @@

#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<UnitManager> m_PlayerUnitManager;
std::shared_ptr<UnitManager> m_AIUnitManager;
std::shared_ptr<AvatarManager> m_AIAvatarManager;
std::shared_ptr<MapClass> m_Map;

std::vector<std::vector<std::shared_ptr<Avatar>>> m_offensiveGroup;
std::vector<std::shared_ptr<Avatar>> m_defensiveGroup;
public:
AIGroupCommander(std::shared_ptr<UnitManager> PlayerUnitManager,std::shared_ptr<UnitManager> AIUnitManager,std::shared_ptr<MapClass> 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(){
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<int>(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<int>(m_defensiveGroup.size());
}

int getOffensiveTroopSize(){
int totalSize = 0;
for (const auto& row : m_offensiveGroup) {
totalSize += static_cast<int>(row.size());
}
return totalSize;
}
protected:
void updateOffensiveGroup(){
for(auto i : m_offensiveGroup){
for(int j=0;j<static_cast<int>(i.size());j++){
if(i[j]->getHealth()->ifDead()){
i.erase(i.begin()+j);
}
}
}
updateOffensiveTroopAttackTarget();
}
void updateDefensiveGroup(){
for(int i = static_cast<int>(m_defensiveGroup.size());i>0;--i ){
if(m_defensiveGroup[i-1]->getHealth()->ifDead()){
m_defensiveGroup.erase(m_defensiveGroup.begin()+i-1);
}else{
autoAttack(m_defensiveGroup[i-1],AUTO_ATTACK_METHOD);
};
}
std::vector<std::shared_ptr<Avatar>> temp = m_AIAvatarManager->getAvatarArray();
for(int i=static_cast<int>(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]);
}
}
}
void addTroopToOffensiveGroup(std::shared_ptr<Avatar> unit){
auto it = std::find_if(m_offensiveGroup.begin(), m_offensiveGroup.end(), [](const std::vector<std::shared_ptr<Avatar>>& 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<std::shared_ptr<Avatar>>());
m_offensiveGroup.back().push_back(unit);
}
}
void autoAttack(std::shared_ptr<Avatar> 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(),HouseType::ENEMY);
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,HouseType::ENEMY);
break;
}
}
void updateOffensiveTroopAttackTarget(){
for(auto i : m_offensiveGroup){
if(i.size()>0){
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);
if (targetCell.x == -1 && targetCell.y == -1) {
return;
}
// attack
for (int j=static_cast<int>(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(
i[j-1], targetCell,HouseType::ENEMY);
}
}
}
}
}
};


class AIGroupCommander {};

#endif // PRACTICALTOOLSFORSIMPLEDESIGN_AIGROUPCOMMANDER_HPP
3 changes: 2 additions & 1 deletion include/AI/EnemyScripts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -17,6 +17,7 @@ class EnemyScripts{
std::shared_ptr<UnitManager> m_GameObjectManager;
std::shared_ptr<UnitManager> m_EnemyObjectManager;
std::shared_ptr<MapClass> m_Map;
std::shared_ptr<AIGroupCommander> m_AIGroupCommander;

glm::vec2 m_baseCell = {20, 20};
int constructCountX = 0;
Expand Down
9 changes: 8 additions & 1 deletion include/Avatar/Avatar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -62,6 +62,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; }

Expand Down Expand Up @@ -104,5 +110,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
1 change: 0 additions & 1 deletion include/Avatar/Infantry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class Infantry : public Avatar {
// setHp(50);
getMoving()->setMovementSpeed(4);
}

private:
};
#endif // PRACTICALTOOLSFORSIMPLEDESIGN_INFANTRY_HPP
29 changes: 29 additions & 0 deletions include/Map/Map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;r<attackRange;r++){
y=r;
for(x=-1*r;x<r;x++){
if(getTileByCellPosition({myCell.x+x,myCell.y+y})->ifEnemyAtTile(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;y<r;y++){
if(getTileByCellPosition({myCell.x+x,myCell.y+y})->ifEnemyAtTile(myHouse)){
return {myCell.x+x,myCell.y+y};
}
}
}
return NullPos;
}
protected:
void InitGrid();

Expand Down
25 changes: 25 additions & 0 deletions include/Map/Tile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,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;
Expand Down
9 changes: 8 additions & 1 deletion include/Mechanics/AvatarManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@ class AvatarManager {

void assignAttackOrderToAvatar(std::shared_ptr<Avatar> unit,
glm::vec2 destcell);

void assignAttackOrderToAvatar(std::shared_ptr<Avatar> avatar,
glm::vec2 destcell,HouseType myHouse);
int getAvatarSize(){
return static_cast<int>(m_AvatarArray.size());
}
bool ifAvatarHasNemesis(std::shared_ptr<Avatar> unit){
return m_NemesisManager->ifAvatarHasNemesis(unit);
}
protected:
void assignOrderToMyAvatar(std::shared_ptr<Avatar> unit);
void updateTileWhileAvatarMoving(std::shared_ptr<Avatar> unit);
Expand Down
6 changes: 2 additions & 4 deletions include/Mechanics/Player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::shared_ptr<Structure>> 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;
}
Expand Down
18 changes: 13 additions & 5 deletions include/Mechanics/UnitManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class UnitManager : public Player {
return m_StructureManager;
}


int updateCurrency();

void spawnToWayPoint(UnitType unit, HouseType house);
Expand All @@ -57,12 +58,20 @@ class UnitManager : public Player {
void addUnitConstructCount(UnitType type, int value) {
unitCount[type] += value;
}
int getUnitConstructCount(UnitType type) { return unitCount[type]; }
int getAvatarCount() { return unitCount[UnitType::INFANTRY]; }
void addAvatarCount(UnitType type, int value) { unitCount[type] += value; }

int getUnitConstructCount(UnitType type){
return unitCount[type];
}
int getAvatarCount(){
return m_AvatarManager->getAvatarSize();;
}





private:
std::unordered_map<UnitType, unsigned int> unitCount;
std::unordered_map<UnitType,int> unitCount;
std::shared_ptr<CursorSelection> m_CursorSelection =
std::make_shared<CursorSelection>();
std::shared_ptr<StructureManager> m_StructureManager =
Expand All @@ -72,7 +81,6 @@ class UnitManager : public Player {
std::shared_ptr<MapClass> m_Map = std::make_shared<MapClass>();
std::chrono::high_resolution_clock::time_point m_StartTime;
double m_lastElapsed = 0.F;
int m_troopSize = 0;
};

#endif // PRACTICALTOOLSFORSIMPLEDESIGN_UNITMANAGER_HPP
2 changes: 0 additions & 2 deletions include/Scene/SandBoxScene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ class SandBoxScene : public Scene {
SpriteSheet m_SpriteSheet;
std::shared_ptr<CursorClass> m_Cursor = std::make_shared<CursorClass>();
Grid testGrid;
std::shared_ptr<EnemyPlayer> m_Enemy =
std::make_shared<EnemyPlayer>(SceneMode::TUTORIAL);
std::shared_ptr<EnemyScripts> m_EnemyScripts =
std::make_shared<EnemyScripts>();
Stages m_stage = Stages::START;
Expand Down
2 changes: 0 additions & 2 deletions include/Scene/TutorialScene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ class TutorialScene : public Scene {
SpriteSheet m_SpriteSheet;
std::shared_ptr<CursorClass> m_Cursor = std::make_shared<CursorClass>();
Grid testGrid;
std::shared_ptr<EnemyPlayer> m_Enemy =
std::make_shared<EnemyPlayer>(SceneMode::TUTORIAL);
std::shared_ptr<EnemyScripts> m_EnemyScripts =
std::make_shared<EnemyScripts>();
std::shared_ptr<Util::GameObject> m_PlayerObjectivesText =
Expand Down
4 changes: 2 additions & 2 deletions include/Structure/AdvencePowerPlants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 1b9c348

Please sign in to comment.