Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
Task_Flee.cpp
Go to the documentation of this file.
1/**
2 * @file Task_Flee.cpp
3 * @brief Atomic AI task: move entity away from a 2D threat position.
4 * @author Olympe Engine
5 * @date 2026-03-08
6 *
7 * C++14 compliant - no C++17/20 features.
8 */
9
10#include "Task_Flee.h"
11#include "../../AtomicTaskRegistry.h"
12#include "../../LocalBlackboard.h"
13#include "../../TaskWorldFacade.h"
14#include "../../../system/system_utils.h"
15
16#include <cmath>
17
18namespace Olympe {
19
20static const float DEFAULT_FLEE_DISTANCE = 200.0f;
21static const float FLEE_MOVE_SPEED = 250.0f;
22
24
26{
27 SYSTEM_LOG << "[Task_Flee(AI)] Abort()\n";
28}
29
31{
32 return TaskStatus::Failure; // requires context; use ExecuteWithContext
33}
34
36 const ParameterMap& params)
37{
38 // --- Resolve TargetX parameter ---
39 float threatX = 0.0f;
40 {
41 auto it = params.find("TargetX");
42 if (it == params.end())
43 {
44 SYSTEM_LOG << "[Task_Flee(AI)] Missing 'TargetX' parameter\n";
46 }
47 if (it->second.GetType() == VariableType::Float)
48 threatX = it->second.AsFloat();
49 else if (it->second.GetType() == VariableType::Int)
50 threatX = static_cast<float>(it->second.AsInt());
51 }
52
53 // --- Resolve TargetY parameter ---
54 float threatY = 0.0f;
55 {
56 auto it = params.find("TargetY");
57 if (it == params.end())
58 {
59 SYSTEM_LOG << "[Task_Flee(AI)] Missing 'TargetY' parameter\n";
61 }
62 if (it->second.GetType() == VariableType::Float)
63 threatY = it->second.AsFloat();
64 else if (it->second.GetType() == VariableType::Int)
65 threatY = static_cast<float>(it->second.AsInt());
66 }
67
68 // --- Resolve Distance parameter (optional) ---
70 {
71 auto it = params.find("Distance");
72 if (it != params.end())
73 {
74 if (it->second.GetType() == VariableType::Float)
75 safeDistance = it->second.AsFloat();
76 else if (it->second.GetType() == VariableType::Int)
77 safeDistance = static_cast<float>(it->second.AsInt());
79 }
80 }
81
83
84 // -----------------------------------------------------------------------
85 // World mode
86 // -----------------------------------------------------------------------
87 if (ctx.ComponentFacade
88 && ctx.ComponentFacade->Position
89 && ctx.ComponentFacade->Movement)
90 {
91 ::Vector& pos = ctx.ComponentFacade->Position->Position;
92 ::Vector& velocity = ctx.ComponentFacade->Movement->Velocity;
93
95 delta.z = 0.0f;
96 const float dist = delta.Norm();
97
98 SYSTEM_LOG << "[Task_Flee(AI)] (WorldMode) Entity " << ctx.Entity
99 << " pos=(" << pos.x << "," << pos.y << ")"
100 << " threat=(" << threatX << "," << threatY << ")"
101 << " dist=" << dist << " safe=" << safeDistance << "\n";
102
103 if (dist >= safeDistance)
104 {
105 velocity = ::Vector(0.0f, 0.0f, 0.0f);
106 return TaskStatus::Success;
107 }
108
109 // Move away from threat.
110 if (dist > 1e-5f)
111 {
112 velocity = delta * (FLEE_MOVE_SPEED / dist);
113 }
114 else
115 {
116 // Entity is on top of threat; flee along +X.
117 velocity = ::Vector(FLEE_MOVE_SPEED, 0.0f, 0.0f);
118 }
119 return TaskStatus::Running;
120 }
121
122 // -----------------------------------------------------------------------
123 // Headless mode: read/write "Position" via LocalBlackboard
124 // -----------------------------------------------------------------------
125 if (!ctx.LocalBB)
126 {
127 SYSTEM_LOG << "[Task_Flee(AI)] No LocalBlackboard and no ComponentFacade\n";
128 return TaskStatus::Success;
129 }
130
131 ::Vector pos(0.0f, 0.0f, 0.0f);
132 {
133 const TaskValue posVal = ctx.LocalBB->GetValueScoped("local:Position");
134 if (posVal.GetType() == VariableType::Vector)
135 {
136 pos = posVal.AsVector();
137 }
138 else if (ctx.LocalBB->HasVariable("Position"))
139 {
140 try { pos = ctx.LocalBB->GetValue("Position").AsVector(); }
141 catch (...) {}
142 }
143 }
144
146 delta.z = 0.0f;
147 const float dist = delta.Norm();
148
149 SYSTEM_LOG << "[Task_Flee(AI)] Entity " << ctx.Entity
150 << " pos=(" << pos.x << "," << pos.y << ")"
151 << " threat=(" << threatX << "," << threatY << ")"
152 << " dist=" << dist << " safe=" << safeDistance << "\n";
153
154 if (dist >= safeDistance)
155 {
156 return TaskStatus::Success;
157 }
158
159 // Compute flee direction and move.
160 const float step = FLEE_MOVE_SPEED * ctx.DeltaTime;
162 if (dist > 1e-5f)
163 {
164 newPos = pos + delta * (step / dist);
165 }
166 else
167 {
168 newPos = pos + ::Vector(step, 0.0f, 0.0f);
169 }
170
171 try
172 {
173 ctx.LocalBB->SetValueScoped("local:Position", TaskValue(newPos));
174 }
175 catch (...)
176 {
177 try { ctx.LocalBB->SetValue("Position", TaskValue(newPos)); }
178 catch (...) {}
179 }
180
181 return TaskStatus::Running;
182}
183
185
186} // namespace Olympe
#define REGISTER_ATOMIC_TASK(ClassName, Id)
Registers a factory for ClassName under Id at static init time.
Atomic task that computes a flee direction away from a target.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
std::unordered_map< std::string, TaskValue > ParameterMap
Convenience alias for the parameter map passed to Execute().
Definition IAtomicTask.h:67
C++14-compliant type-safe value container for task parameters.
::Vector AsVector() const
Returns the Vector value.
Moves an entity away from a 2D threat position until safe distance is reached.
Definition Task_Flee.h:36
void Abort() override
Aborts the task, releasing any in-progress state.
Definition Task_Flee.cpp:25
TaskStatus Execute(const ParameterMap &params) override
Executes the atomic task for one frame.
Definition Task_Flee.cpp:30
TaskStatus ExecuteWithContext(const AtomicTaskContext &ctx, const ParameterMap &params) override
Executes the atomic task for one frame with full runtime context.
Definition Task_Flee.cpp:35
float z
Definition vector.h:25
< Provides AssetID and INVALID_ASSET_ID
static const float FLEE_MOVE_SPEED
Definition Task_Flee.cpp:21
@ Int
32-bit signed integer
@ Float
Single-precision float.
@ Vector
3-component vector (Vector from vector.h)
TaskStatus
Result code returned by IAtomicTask::Execute().
Definition IAtomicTask.h:38
@ Success
Task completed successfully.
@ Running
Task is still in progress (multi-frame tasks)
@ Failure
Task failed.
static const float DEFAULT_FLEE_DISTANCE
Definition Task_Flee.cpp:20
Lightweight context bundle passed to IAtomicTask::ExecuteWithContext().
#define SYSTEM_LOG