Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
mazeraider/src/EnemyAI.cpp
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
326 lines (266 sloc)
8.64 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "EnemyAI.h" | |
#include "Maze.h" | |
#include "LevelManager.h" | |
#include "Player.h" | |
#include "UIHelpers.h" | |
#include "Enemy.h" | |
#include "UI.h" | |
using namespace UIHelpers; | |
EnemyAI::EnemyAI(shared_ptr<LevelManager> lvlman) | |
{ | |
lvlManager = lvlman; | |
} | |
void EnemyAI::getNextPosition(shared_ptr<Enemy> enemy) | |
{ | |
if(shared_ptr<LevelManager> lvlman = lvlManager.lock()) | |
{ | |
if (abs(lvlman->player->xPos - enemy->xPos) < followPlayerLimit || | |
abs(lvlman->player->yPos - enemy->yPos) < followPlayerLimit ) | |
{ | |
string m = "An enemy just felt you, it's coming to find you!"; | |
if(lvlman->ui->mazeInfo[lvlman->ui->mazeInfo.size() - 1].first != m) | |
UpdateMessageInfo(lvlman->ui->mazeInfo, m, MessageType::Enemy); | |
enemy->followingPlayer = true; | |
vector<pos> path = findPath({enemy->xPos, enemy->yPos}); | |
//DEBUG | |
//debugPrintNodes(path); | |
//system("pause"); | |
// (1, 0) = Parent at right | (-1, 0) = Parent at Left | (0, 1) = Parent at Top | (0, -1) = Parent at Bottom | |
pos dir = path[1] - path[0]; | |
pos nextPos; | |
for(pos p : path) | |
{ | |
if((p.X != path[0].X && dir.X == 0) || (p.Y != path[0].Y && dir.Y == 0)) | |
break; | |
else | |
{ | |
enemy->xPos = p.X; | |
enemy->yPos = p.Y; | |
} | |
} | |
} | |
else | |
{ | |
enemy->followingPlayer = false; | |
enemy->randomMoveEnemy(); | |
} | |
} | |
} | |
// Find shortest path to player | |
vector<EnemyAI::pos> EnemyAI::findPath(pos p) | |
{ | |
if(shared_ptr<LevelManager> lvlman = lvlManager.lock()) | |
{ | |
pos startPosition = p; | |
pos destPosition = {lvlman->player->xPos, lvlman->player->yPos}; | |
vector<node> openList; | |
vector<node> closeList; | |
node currNode; | |
currNode.position = startPosition; | |
currNode.F = 0; | |
currNode.G = 0; | |
currNode.H = 0; | |
currNode.parent.X = 0; | |
currNode.parent.Y = 0; | |
openList.emplace_back(currNode); | |
while (openList.size() > 0) | |
{ | |
if(currNode.position == destPosition) | |
break; | |
closeList.emplace_back(currNode); | |
auto it = find(openList.begin(), openList.end(), currNode); | |
if (it != openList.end()) | |
openList.erase(it); | |
vector<node> tempList = checkNodes(currNode, startPosition, destPosition, closeList); | |
openList.insert(openList.end(), tempList.begin(), tempList.end()); | |
sort(openList.begin(), openList.end()); | |
vector<node> sameFValue; | |
sameFValue.emplace_back(openList[0]); | |
for(node n : openList) | |
{ | |
if(n.F == sameFValue[0].F) | |
sameFValue.emplace_back(n); | |
else | |
break; | |
} | |
if(sameFValue.size() > 1) | |
sort(sameFValue.begin(), sameFValue.end(), node::compareH); | |
currNode = sameFValue[0]; | |
} | |
//DEBUG | |
//debugPrintNodes(openList, closeList); | |
//system("pause"); | |
//debugPrintNodes(closeList); | |
//system("pause"); | |
vector<pos> path; | |
path.emplace_back(currNode.position); | |
while(currNode.position != startPosition) | |
{ | |
for(node n : closeList) | |
{ | |
if(n.position == currNode.parent) | |
{ | |
path.insert(path.begin(), n.position); | |
currNode = n; | |
break; | |
} | |
} | |
} | |
return path; | |
} | |
} | |
// Check surrounding nodes | |
vector<EnemyAI::node> EnemyAI::checkNodes(node cNode, pos sPosition, pos dPosition, vector<node>& closed) | |
{ | |
vector<node> tList; | |
node tempNode; | |
array<pos, 4> directions; | |
directions[0] = {1, 0}; | |
directions[1] = {-1, 0}; | |
directions[2] = {0, 1}; | |
directions[3] = {0, -1}; | |
for(pos dir : directions) | |
{ | |
bool notChecked = true; | |
for(node n : closed) | |
if(n.position == cNode.position + dir) | |
{ | |
if(n.F < cNode.F) | |
{ | |
n.parent = cNode.position; | |
// Distance from starting position | |
n.G = cNode.G + 1; | |
// Distance from destination position | |
n.H = cNode.H + 1; | |
// Sum of both distances | |
n.F = n.G + n.H; | |
} | |
notChecked = false; | |
continue; | |
} | |
// 0 = to path | |
if(notChecked && | |
lvlManager.lock()->maze->getMazeArray()[cNode.position.X + dir.X][cNode.position.Y + dir.Y] == 0) | |
{ | |
tempNode.position = cNode.position + dir; | |
tempNode.parent = cNode.position; | |
// Distance from starting position | |
tempNode.G = abs(tempNode.position.X - sPosition.X) + abs(tempNode.position.Y - sPosition.Y); | |
// Distance from destination position | |
tempNode.H = abs(tempNode.position.X - dPosition.X) + abs(tempNode.position.Y - dPosition.Y); | |
// Sum of both distances | |
tempNode.F = tempNode.G + tempNode.H; | |
tList.emplace_back(tempNode); | |
} | |
} | |
return tList; | |
} | |
// DEBUG | |
void EnemyAI::debugPrintNodeF(node n, int colour) | |
{ | |
#ifdef _WIN32 | |
HANDLE hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); | |
CONSOLE_SCREEN_BUFFER_INFO cbsi; | |
GetConsoleScreenBufferInfo(hStdOut, &cbsi); | |
COORD originalPos = cbsi.dwCursorPosition; | |
#endif // _WIN32 | |
#ifdef __linux__ | |
int hStdOut; | |
cout << "\033[s"; | |
#endif // __linux__ | |
cursorPosition(hStdOut, n.position.X * 2, n.position.Y + 3); | |
if(n.F < 10) | |
PrintC(to_string(n.F), colour, true); | |
else | |
PrintC(to_string(n.F), colour); | |
#ifdef _WIN32 | |
SetConsoleCursorPosition( hStdOut, originalPos ); | |
#endif // _WIN32 | |
#ifdef __linux__ | |
cout << "\033[u"; | |
#endif // __linux__ | |
} | |
void EnemyAI::debugPrintNodeParent(pos p, pos dir) | |
{ | |
#ifdef _WIN32 | |
HANDLE hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); | |
CONSOLE_SCREEN_BUFFER_INFO cbsi; | |
GetConsoleScreenBufferInfo(hStdOut, &cbsi); | |
COORD originalPos = cbsi.dwCursorPosition; | |
#endif // _WIN32 | |
#ifdef __linux__ | |
int hStdOut; | |
cout << "\033[s"; | |
#endif // __linux__ | |
cursorPosition(hStdOut, p.X * 2, p.Y + 3); | |
// (1, 0) = Parent at right | (-1, 0) = Parent at Left | (0, 1) = Parent at Top | (0, -1) = Parent at Bottom | |
if(dir.X == 1 && dir.Y == 0) | |
PrintC(" >", 3); | |
else if(dir.X == -1 && dir.Y == 0) | |
PrintC("< ", 3); | |
else if(dir.X == 0 && dir.Y == -1) | |
PrintC(R"(/\)", 3); | |
else if(dir.X == 0 && dir.Y == 1) | |
PrintC(R"(\/)", 3); | |
#ifdef _WIN32 | |
SetConsoleCursorPosition( hStdOut, originalPos ); | |
#endif // _WIN32 | |
#ifdef __linux__ | |
cout << "\033[u"; | |
#endif // __linux__ | |
} | |
void EnemyAI::debugPrintNodes(vector<node> showValueOpenL, vector<node> showValueClosedL) | |
{ | |
for(node n : showValueOpenL) | |
debugPrintNodeF(n, 164); | |
for(node n : showValueClosedL) | |
debugPrintNodeF(n, 192); | |
} | |
void EnemyAI::debugPrintNodes(vector<node> showParentList) | |
{ | |
#ifdef _WIN32 | |
HANDLE hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); | |
CONSOLE_SCREEN_BUFFER_INFO cbsi; | |
GetConsoleScreenBufferInfo(hStdOut, &cbsi); | |
COORD originalPos = cbsi.dwCursorPosition; | |
#endif // _WIN32 | |
#ifdef __linux__ | |
int hStdOut; | |
cout << "\033[s"; | |
#endif // __linux__ | |
for(node n : showParentList) | |
{ | |
pos dir = n.parent - n.position; | |
debugPrintNodeParent(n.position, dir); | |
} | |
#ifdef _WIN32 | |
SetConsoleCursorPosition( hStdOut, originalPos ); | |
#endif // _WIN32 | |
#ifdef __linux__ | |
cout << "\033[u"; | |
#endif // __linux__ | |
} | |
void EnemyAI::debugPrintNodes(vector<pos> showParentList) | |
{ | |
#ifdef _WIN32 | |
HANDLE hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); | |
CONSOLE_SCREEN_BUFFER_INFO cbsi; | |
GetConsoleScreenBufferInfo(hStdOut, &cbsi); | |
COORD originalPos = cbsi.dwCursorPosition; | |
#endif // _WIN32 | |
#ifdef __linux__ | |
int hStdOut; | |
cout << "\033[s"; | |
#endif // __linux__ | |
for(unsigned i = 0; i < showParentList.size() - 1; i++) | |
{ | |
pos dir = showParentList[i] - showParentList[i - 1]; | |
debugPrintNodeParent(showParentList[i], dir); | |
} | |
#ifdef _WIN32 | |
SetConsoleCursorPosition( hStdOut, originalPos ); | |
#endif // _WIN32 | |
#ifdef __linux__ | |
cout << "\033[u"; | |
#endif // __linux__ | |
} |