summaryrefslogtreecommitdiff
path: root/engine-ocean/Game/Systems/AI
diff options
context:
space:
mode:
authorjjesswan <jessica_wan@brown.edu>2024-04-22 21:56:26 -0400
committerjjesswan <jessica_wan@brown.edu>2024-04-22 21:56:26 -0400
commita556b45abf18f1bd509daaf63b66b7d55e9fd291 (patch)
treebc9b8a2d184c12aee236e7f9f276a34b84ca552d /engine-ocean/Game/Systems/AI
parentcd7c76017a12bb548036571c1ff13e551369d06d (diff)
add engine version
Diffstat (limited to 'engine-ocean/Game/Systems/AI')
-rw-r--r--engine-ocean/Game/Systems/AI/Actions/btaction.cpp6
-rw-r--r--engine-ocean/Game/Systems/AI/Actions/btaction.h17
-rw-r--r--engine-ocean/Game/Systems/AI/Actions/walkaction.cpp90
-rw-r--r--engine-ocean/Game/Systems/AI/Actions/walkaction.h29
-rw-r--r--engine-ocean/Game/Systems/AI/Conditions/btcondition.cpp6
-rw-r--r--engine-ocean/Game/Systems/AI/Conditions/btcondition.h18
-rw-r--r--engine-ocean/Game/Systems/AI/Conditions/proximitycondition.cpp43
-rw-r--r--engine-ocean/Game/Systems/AI/Conditions/proximitycondition.h27
-rw-r--r--engine-ocean/Game/Systems/AI/aibehaviorcomponent.cpp46
-rw-r--r--engine-ocean/Game/Systems/AI/aibehaviorcomponent.h27
-rw-r--r--engine-ocean/Game/Systems/AI/btnode.cpp6
-rw-r--r--engine-ocean/Game/Systems/AI/btnode.h18
-rw-r--r--engine-ocean/Game/Systems/AI/btselector.cpp29
-rw-r--r--engine-ocean/Game/Systems/AI/btselector.h21
-rw-r--r--engine-ocean/Game/Systems/AI/btsequence.cpp30
-rw-r--r--engine-ocean/Game/Systems/AI/btsequence.h20
16 files changed, 433 insertions, 0 deletions
diff --git a/engine-ocean/Game/Systems/AI/Actions/btaction.cpp b/engine-ocean/Game/Systems/AI/Actions/btaction.cpp
new file mode 100644
index 0000000..1b35340
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Actions/btaction.cpp
@@ -0,0 +1,6 @@
+#include "btaction.h"
+
+BTAction::BTAction()
+{
+
+}
diff --git a/engine-ocean/Game/Systems/AI/Actions/btaction.h b/engine-ocean/Game/Systems/AI/Actions/btaction.h
new file mode 100644
index 0000000..180f72c
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Actions/btaction.h
@@ -0,0 +1,17 @@
+#ifndef BTACTION_H
+#define BTACTION_H
+#include "Game/Systems/AI/btnode.h"
+
+class BTAction : public BTNode
+{
+public:
+ BTAction();
+ virtual Status update(float seconds) = 0;
+ virtual void reset() = 0;
+
+private:
+ Status m_status;
+
+};
+
+#endif // BTACTION_H
diff --git a/engine-ocean/Game/Systems/AI/Actions/walkaction.cpp b/engine-ocean/Game/Systems/AI/Actions/walkaction.cpp
new file mode 100644
index 0000000..6a6d116
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Actions/walkaction.cpp
@@ -0,0 +1,90 @@
+#include "walkaction.h"
+#include "Game/Components/PathfindComponent.h"
+#include "Game/Components/TransformComponent.h"
+#include "Game/GameObjects/GameObject.h"
+#include "glm/glm.hpp"
+#include <memory>
+
+
+WalkAction::WalkAction(std::string entity_id,
+ std::map<std::string, BlackboardData>& global_blackboard):
+ m_global_blackboard(global_blackboard)
+{
+
+ m_entity_id = entity_id;
+ m_path.clear();
+
+ m_global_blackboard[m_entity_id].conditionData["isPathfinding"].conditionTrue = false;
+ m_global_blackboard[m_entity_id].conditionData["atDestination"].conditionTrue = false;
+ m_global_blackboard[m_entity_id].conditionData["pathfound"].conditionTrue = false;
+
+
+
+
+}
+
+void WalkAction::setPath(glm::vec3 entity_pos){
+ std::cout << "---------SETTING PATHH" << std::endl;
+ m_destination = m_global_blackboard["player"].locationData.currPos;
+ m_path = m_global_blackboard["navmesh"].environment->getComponent<PathfindComponent>()->getPath(glm::vec3(-0.58249, 0, -0.0210782), glm::vec3(19.5371, 0, 1.39167));
+}
+
+// only activates if the previous conditions are true
+Status WalkAction::update(float seconds){
+
+ glm::vec3 pos = m_global_blackboard[m_entity_id].locationData.currPos;
+
+ // get a path if entity is not pathfinding
+ if (!m_global_blackboard[m_entity_id].conditionData["isPathfinding"].conditionTrue &&
+ !m_global_blackboard[m_entity_id].conditionData["atDestination"].conditionTrue &&
+ !m_global_blackboard[m_entity_id].conditionData["pathfound"].conditionTrue){
+ setPath(pos);
+ m_global_blackboard[m_entity_id].conditionData["isPathfinding"].conditionTrue = true;
+ m_global_blackboard[m_entity_id].conditionData["pathfound"].conditionTrue = true;
+
+ }
+
+ if (!m_path.empty()){
+ if (m_global_blackboard[m_entity_id].conditionData["onGround"].conditionTrue){
+ //std::cout << "on ground" << std::endl;
+
+ std::shared_ptr<ModelTransform> temp_mt = std::make_shared<ModelTransform>();
+ temp_mt->setPos(pos);
+ glm::vec3 v = m_path.back();//glm::vec3(m_path.back().x, pos.y, m_path.back().z);
+ glm::vec3 dir = glm::normalize(v-temp_mt->getPos());
+ temp_mt->translate(dir);
+ //std::cout << "v: (" << v.x << ", " << v.y << ", " << v.z << ")" << std::endl;
+ glm::vec3 pos_eps = v + .01f;
+ glm::vec3 neg_eps = v - .01f;
+
+ // pop if entity within a certain episilon of node
+ if (neg_eps.x < temp_mt->getPos().x < pos_eps.x &&
+ neg_eps.z < temp_mt->getPos().z < pos_eps.z){
+ m_path.pop_back();
+ }
+
+ m_global_blackboard[m_entity_id].locationData.setToPos = temp_mt->getPos();
+ }
+
+ return Status::RUNNING;
+ }
+
+ // if reached destination, then walking succeeded
+ if (pos.x == m_destination.x && pos.z == m_destination.z){
+ m_global_blackboard[m_entity_id].conditionData["isPathfinding"].conditionTrue = false;
+ m_global_blackboard[m_entity_id].conditionData["atDestination"].conditionTrue = true;
+ std::cout << "-reached-" << std::endl;
+ return Status::SUCCESS;
+
+ }
+
+ // otherwise
+ m_global_blackboard[m_entity_id].conditionData["isPathfinding"].conditionTrue = false;
+ return Status::FAIL;
+
+}
+
+void WalkAction::reset(){}
+void WalkAction::addChildren(BTNode *node){}
+
+
diff --git a/engine-ocean/Game/Systems/AI/Actions/walkaction.h b/engine-ocean/Game/Systems/AI/Actions/walkaction.h
new file mode 100644
index 0000000..2e24864
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Actions/walkaction.h
@@ -0,0 +1,29 @@
+#ifndef WALKACTION_H
+#define WALKACTION_H
+#include "Game/Components/TransformComponent.h"
+#include "Game/GameObjects/GameObject.h"
+#include "Game/Systems/AI/btnode.h"
+#include "glm/fwd.hpp"
+#include <memory>
+#include "btaction.h"
+
+class WalkAction : public BTNode
+{
+public:
+ WalkAction(std::string entity_id, std::map<std::string, BlackboardData>& global_blackboard);
+ Status update(float seconds) override;
+ void reset() override;
+ void setPath(glm::vec3 entity_pos);
+ void addChildren(BTNode *node) override;
+
+
+
+private:
+ std::vector<glm::vec3> m_path;
+ glm::vec3 m_destination;
+ std::map<std::string, BlackboardData>& m_global_blackboard;
+ std::string m_entity_id;
+};
+
+
+#endif // WALKACTION_H
diff --git a/engine-ocean/Game/Systems/AI/Conditions/btcondition.cpp b/engine-ocean/Game/Systems/AI/Conditions/btcondition.cpp
new file mode 100644
index 0000000..f4de4af
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Conditions/btcondition.cpp
@@ -0,0 +1,6 @@
+#include "btcondition.h"
+
+BTCondition::BTCondition()
+{
+
+}
diff --git a/engine-ocean/Game/Systems/AI/Conditions/btcondition.h b/engine-ocean/Game/Systems/AI/Conditions/btcondition.h
new file mode 100644
index 0000000..6ded57b
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Conditions/btcondition.h
@@ -0,0 +1,18 @@
+#ifndef BTCONDITION_H
+#define BTCONDITION_H
+#include "Game/Systems/AI/btnode.h"
+
+
+class BTCondition : public BTNode
+{
+public:
+ BTCondition();
+ virtual Status update(float seconds) = 0;
+ virtual void reset() = 0;
+
+
+private:
+ bool m_condition;
+};
+
+#endif // BTCONDITION_H
diff --git a/engine-ocean/Game/Systems/AI/Conditions/proximitycondition.cpp b/engine-ocean/Game/Systems/AI/Conditions/proximitycondition.cpp
new file mode 100644
index 0000000..2e40ce7
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Conditions/proximitycondition.cpp
@@ -0,0 +1,43 @@
+#include "proximitycondition.h"
+#include "Game/Components/TransformComponent.h"
+#include "glm/glm.hpp"
+#include <memory>
+
+ProximityCondition::ProximityCondition(std::string entity_id,
+ std::map<std::string, BlackboardData>& global_blackboard,
+ float proximity):
+ m_global_blackboard(global_blackboard)
+{
+ m_proximity = proximity;
+ m_entity_id = entity_id;
+ // initialize just in case
+ m_global_blackboard["player"].conditionData["isJumping"].conditionTrue = false;
+
+
+}
+
+// maybe can check locations from blackboard
+// pass blackboard into constructor
+// struct: positiondata --> getCurrentPos, setCurrentPos
+bool ProximityCondition::checkProximity(){
+ // unrooted distance
+ glm::vec3 aiPos = m_global_blackboard[m_entity_id].locationData.currPos;
+ glm::vec3 otherPos = m_global_blackboard["player"].locationData.currPos;
+ float distance = pow(aiPos.x-otherPos.x, 2) + pow(aiPos.y-otherPos.y, 2) + pow(aiPos.z-otherPos.z, 2);
+
+ if (distance <= m_proximity) return true;
+ return false;
+}
+
+// at every update, check if AIPos is near otherPos
+Status ProximityCondition::update(float seconds){
+ // while entity is still pathfinding, keep returning success
+ if (m_global_blackboard[m_entity_id].conditionData["isPathfinding"].conditionTrue) return Status::SUCCESS;
+ if (checkProximity() && m_global_blackboard["player"].conditionData["isJumping"].conditionTrue) return Status::SUCCESS;
+
+ return Status::FAIL;
+}
+
+
+void ProximityCondition::reset(){}
+void ProximityCondition::addChildren(BTNode *node){}
diff --git a/engine-ocean/Game/Systems/AI/Conditions/proximitycondition.h b/engine-ocean/Game/Systems/AI/Conditions/proximitycondition.h
new file mode 100644
index 0000000..e43d178
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/Conditions/proximitycondition.h
@@ -0,0 +1,27 @@
+#ifndef PROXIMITYCONDITION_H
+#define PROXIMITYCONDITION_H
+#include "Game/Components/TransformComponent.h"
+#include "btcondition.h"
+#include <memory>
+
+
+class ProximityCondition : public BTNode
+{
+public:
+ ProximityCondition(std::string entity_id,
+ std::map<std::string, BlackboardData>& global_blackboard,
+ float proximity);
+ Status update(float seconds) override;
+ void reset() override;
+ void addChildren(BTNode *node) override;
+
+
+private:
+ bool checkProximity();
+ float m_proximity;
+ std::string m_entity_id;
+ std::map<std::string, BlackboardData>& m_global_blackboard;
+
+};
+
+#endif // PROXIMITYCONDITION_H
diff --git a/engine-ocean/Game/Systems/AI/aibehaviorcomponent.cpp b/engine-ocean/Game/Systems/AI/aibehaviorcomponent.cpp
new file mode 100644
index 0000000..b43ed07
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/aibehaviorcomponent.cpp
@@ -0,0 +1,46 @@
+#include "aibehaviorcomponent.h"
+#include "Game/Systems/AI/Actions/walkaction.h"
+#include "Game/Systems/AI/Conditions/proximitycondition.h"
+#include "Game/Systems/AI/btselector.h"
+#include "Game/Systems/AI/btsequence.h"
+
+AIBehaviorComponent::AIBehaviorComponent(std::string entity_id,
+ std::map<std::string, BlackboardData>& global_blackboard):
+ m_global_blackboard(global_blackboard)
+{
+ m_entity_id = entity_id;
+ makeBehaviorTree();
+
+}
+
+void AIBehaviorComponent::makeBehaviorTree(){
+ // leaves
+ //std::unique_ptr<BTNode> walk = std::make_unique<WalkAction>(m_entity_id, m_global_blackboard);
+ BTNode *proximCond = new ProximityCondition(m_entity_id, m_global_blackboard, 20.f);
+ BTNode *walk = new WalkAction(m_entity_id, m_global_blackboard);
+
+
+// // pathfind sequence
+ BTNode *pathfindSeq = new BTSequence;
+ pathfindSeq->addChildren(proximCond);
+ pathfindSeq->addChildren(walk);
+
+// // idle sequence
+
+// // root
+ m_root = new BTSelector;
+ m_root->addChildren(pathfindSeq);
+}
+
+// how might i be able to generalize the creation of the tree?
+void AIBehaviorComponent::update(float seconds){
+ // update root, which updates all its children
+ //std::cout << "---------in ai system" << std::endl;
+
+ m_status = m_root->update(seconds);
+}
+
+AIBehaviorComponent::~AIBehaviorComponent(){
+ delete m_root;
+}
+
diff --git a/engine-ocean/Game/Systems/AI/aibehaviorcomponent.h b/engine-ocean/Game/Systems/AI/aibehaviorcomponent.h
new file mode 100644
index 0000000..5a86b88
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/aibehaviorcomponent.h
@@ -0,0 +1,27 @@
+#ifndef AIBEHAVIORCOMPONENT_H
+#define AIBEHAVIORCOMPONENT_H
+
+
+#include "Game/Components/Component.h"
+#include "Game/Systems/AI/btselector.h"
+#include "Game/Systems/aisystem.h"
+#include <map>
+#include <string>
+class AIBehaviorComponent : public Component
+{
+public:
+ AIBehaviorComponent(std::string entity_id,
+ std::map<std::string, BlackboardData>& global_blackboard);
+ ~AIBehaviorComponent();
+ void update(float seconds);
+
+private:
+ void makeBehaviorTree();
+
+ std::string m_entity_id;
+ std::map<std::string, BlackboardData>& m_global_blackboard;
+ BTNode *m_root = 0;
+ Status m_status = Status::SUCCESS;
+};
+
+#endif // AIBEHAVIORCOMPONENT_H
diff --git a/engine-ocean/Game/Systems/AI/btnode.cpp b/engine-ocean/Game/Systems/AI/btnode.cpp
new file mode 100644
index 0000000..2740089
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/btnode.cpp
@@ -0,0 +1,6 @@
+#include "btnode.h"
+
+BTNode::BTNode()
+{
+
+}
diff --git a/engine-ocean/Game/Systems/AI/btnode.h b/engine-ocean/Game/Systems/AI/btnode.h
new file mode 100644
index 0000000..b025da6
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/btnode.h
@@ -0,0 +1,18 @@
+#ifndef BTNODE_H
+#define BTNODE_H
+
+
+enum Status{
+ SUCCESS, FAIL, RUNNING
+};
+
+class BTNode
+{
+public:
+ BTNode();
+ virtual ~BTNode() = default;
+ virtual Status update(float seconds) = 0;
+ virtual void reset() = 0;
+ virtual void addChildren(BTNode *node) = 0;
+};
+#endif // BTNODE_H
diff --git a/engine-ocean/Game/Systems/AI/btselector.cpp b/engine-ocean/Game/Systems/AI/btselector.cpp
new file mode 100644
index 0000000..9652838
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/btselector.cpp
@@ -0,0 +1,29 @@
+#include "btselector.h"
+#include <iostream>
+
+BTSelector::BTSelector()
+{
+
+}
+
+void BTSelector::addChildren(BTNode* node){
+ m_children.push_back(node);
+}
+
+Status BTSelector::update(float seconds){
+ // update each children until one doesnt fail
+ for (auto node : m_children){
+ Status result = node->update(seconds);
+
+ // select this one and return its status --> this node is currently running
+ if (result != Status::FAIL){
+ m_selected_node = node;
+ return result;
+ }
+ }
+
+ // otherwise if all children fail, then fail this selector
+ return Status::FAIL;
+}
+
+void BTSelector::reset(){}
diff --git a/engine-ocean/Game/Systems/AI/btselector.h b/engine-ocean/Game/Systems/AI/btselector.h
new file mode 100644
index 0000000..20058ac
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/btselector.h
@@ -0,0 +1,21 @@
+#ifndef BTSELECTOR_H
+#define BTSELECTOR_H
+#include "Game/Systems/AI/btnode.h"
+#include <vector>
+
+
+class BTSelector : public BTNode
+{
+public:
+ BTSelector();
+ Status update(float seconds) override;
+ void reset() override;
+ void addChildren(BTNode *node) override;
+
+
+private:
+ std::vector<BTNode *> m_children;
+ BTNode *m_selected_node;
+};
+
+#endif // BTSELECTOR_H
diff --git a/engine-ocean/Game/Systems/AI/btsequence.cpp b/engine-ocean/Game/Systems/AI/btsequence.cpp
new file mode 100644
index 0000000..ba6169d
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/btsequence.cpp
@@ -0,0 +1,30 @@
+#include "btsequence.h"
+#include <vector>
+
+BTSequence::BTSequence()
+{
+
+}
+
+void BTSequence::addChildren(BTNode *node){
+ m_sequence.push_back(node);
+}
+
+Status BTSequence::update(float seconds){
+
+ for (auto node : m_sequence){
+ if (node->update(seconds) == Status::FAIL){
+ return Status::RUNNING;
+ }
+ // if come across any node that fails
+ if (node->update(seconds) == Status::FAIL){
+ return Status::FAIL;
+ }
+ }
+
+ // if no node is fail or running, sequence is completed
+ return Status::SUCCESS;
+}
+
+void BTSequence::reset(){}
+
diff --git a/engine-ocean/Game/Systems/AI/btsequence.h b/engine-ocean/Game/Systems/AI/btsequence.h
new file mode 100644
index 0000000..5ff230c
--- /dev/null
+++ b/engine-ocean/Game/Systems/AI/btsequence.h
@@ -0,0 +1,20 @@
+#ifndef BTSEQUENCE_H
+#define BTSEQUENCE_H
+#include "btnode.h"
+#include <vector>
+
+
+class BTSequence : public BTNode
+{
+public:
+ BTSequence();
+ Status update(float seconds) override;
+ void reset() override;
+ void addChildren(BTNode* node) override;
+
+
+private:
+ std::vector<BTNode *> m_sequence;
+};
+
+#endif // BTSEQUENCE_H