Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
Task_GotoPosition.cpp
Go to the documentation of this file.
1/**
2 * @file Task_GotoPosition.cpp
3 * @brief Atomic task: move entity toward a 2D target 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_GotoPosition.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_GOTO_SPEED = 300.0f;
21static const float ARRIVAL_TOLERANCE = 5.0f;
22static const char* BB_KEY_POSITION = "Position";
23
25
27{
28 SYSTEM_LOG << "[Task_GotoPosition] Abort()\n";
29}
30
32{
33 return TaskStatus::Failure; // requires context; use ExecuteWithContext
34}
35
37 const ParameterMap& params)
38{
39 // --- Resolve TargetX parameter ---
40 float targetX = 0.0f;
41 {
42 auto it = params.find("TargetX");
43 if (it == params.end())
44 {
45 SYSTEM_LOG << "[Task_GotoPosition] Missing 'TargetX' parameter\n";
47 }
48 if (it->second.GetType() == VariableType::Float)
49 {
50 targetX = it->second.AsFloat();
51 }
52 else if (it->second.GetType() == VariableType::Int)
53 {
54 targetX = static_cast<float>(it->second.AsInt());
55 }
56 }
57
58 // --- Resolve TargetY parameter ---
59 float targetY = 0.0f;
60 {
61 auto it = params.find("TargetY");
62 if (it == params.end())
63 {
64 SYSTEM_LOG << "[Task_GotoPosition] Missing 'TargetY' parameter\n";
66 }
67 if (it->second.GetType() == VariableType::Float)
68 {
69 targetY = it->second.AsFloat();
70 }
71 else if (it->second.GetType() == VariableType::Int)
72 {
73 targetY = static_cast<float>(it->second.AsInt());
74 }
75 }
76
77 // --- Resolve Speed parameter (optional) ---
78 float speed = DEFAULT_GOTO_SPEED;
79 {
80 auto it = params.find("Speed");
81 if (it != params.end())
82 {
83 if (it->second.GetType() == VariableType::Float)
84 speed = it->second.AsFloat();
85 else if (it->second.GetType() == VariableType::Int)
86 speed = static_cast<float>(it->second.AsInt());
87 if (speed <= 0.0f) speed = DEFAULT_GOTO_SPEED;
88 }
89 }
90
91 ::Vector target(targetX, targetY, 0.0f);
92
93 // -----------------------------------------------------------------------
94 // World mode: use ECS PositionComponent + MovementComponent when available
95 // -----------------------------------------------------------------------
96 if (ctx.ComponentFacade
97 && ctx.ComponentFacade->Position
98 && ctx.ComponentFacade->Movement)
99 {
100 ::Vector& pos = ctx.ComponentFacade->Position->Position;
101 ::Vector& velocity = ctx.ComponentFacade->Movement->Velocity;
102
103 ::Vector delta = target - pos;
104 delta.z = 0.0f; // 2D movement
105 const float dist = delta.Norm();
106
107 SYSTEM_LOG << "[Task_GotoPosition] (WorldMode) Entity " << ctx.Entity
108 << " pos=(" << pos.x << "," << pos.y << ")"
109 << " target=(" << targetX << "," << targetY << ")"
110 << " dist=" << dist << "\n";
111
112 if (dist <= ARRIVAL_TOLERANCE)
113 {
114 velocity = ::Vector(0.0f, 0.0f, 0.0f);
115 return TaskStatus::Success;
116 }
117
118 ::Vector dir = delta * (1.0f / dist);
119 velocity = dir * speed;
120 return TaskStatus::Running;
121 }
122
123 // -----------------------------------------------------------------------
124 // Headless mode: read/write "Position" via LocalBlackboard
125 // -----------------------------------------------------------------------
126 if (!ctx.LocalBB)
127 {
128 SYSTEM_LOG << "[Task_GotoPosition] No LocalBlackboard and no ComponentFacade\n";
129 return TaskStatus::Success; // safe default in test mode
130 }
131
132 // Read current position from blackboard.
133 ::Vector pos(0.0f, 0.0f, 0.0f);
134 {
135 const TaskValue posVal = ctx.LocalBB->GetValueScoped("local:Position");
136 if (posVal.GetType() == VariableType::Vector)
137 {
138 pos = posVal.AsVector();
139 }
140 else if (ctx.LocalBB->HasVariable(BB_KEY_POSITION))
141 {
142 try { pos = ctx.LocalBB->GetValue(BB_KEY_POSITION).AsVector(); }
143 catch (...) {}
144 }
145 }
146
147 ::Vector delta = target - pos;
148 delta.z = 0.0f;
149 const float dist = delta.Norm();
150
151 SYSTEM_LOG << "[Task_GotoPosition] Entity " << ctx.Entity
152 << " pos=(" << pos.x << "," << pos.y << ")"
153 << " target=(" << targetX << "," << targetY << ")"
154 << " dist=" << dist << "\n";
155
156 if (dist <= ARRIVAL_TOLERANCE)
157 {
158 return TaskStatus::Success;
159 }
160
161 const float step = speed * ctx.DeltaTime;
162 ::Vector newPos = (dist <= step)
163 ? target
164 : pos + delta * (step / dist);
165
166 // Write updated position back.
167 try
168 {
169 ctx.LocalBB->SetValueScoped("local:Position", TaskValue(newPos));
170 }
171 catch (...)
172 {
173 try { ctx.LocalBB->SetValue(BB_KEY_POSITION, TaskValue(newPos)); }
174 catch (...) {}
175 }
176
177 return TaskStatus::Running;
178}
179
180REGISTER_ATOMIC_TASK(Task_GotoPosition, "Task_GotoPosition")
181
182} // namespace Olympe
#define REGISTER_ATOMIC_TASK(ClassName, Id)
Registers a factory for ClassName under Id at static init time.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Atomic task that moves an entity toward a 2D target position.
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 toward a 2D (TargetX, TargetY) destination.
TaskStatus ExecuteWithContext(const AtomicTaskContext &ctx, const ParameterMap &params) override
Executes the atomic task for one frame with full runtime context.
TaskStatus Execute(const ParameterMap &params) override
Executes the atomic task for one frame.
void Abort() override
Aborts the task, releasing any in-progress state.
float z
Definition vector.h:25
< Provides AssetID and INVALID_ASSET_ID
@ Int
32-bit signed integer
@ Float
Single-precision float.
@ Vector
3-component vector (Vector from vector.h)
static const float DEFAULT_GOTO_SPEED
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 ARRIVAL_TOLERANCE
static const char * BB_KEY_POSITION
Lightweight context bundle passed to IAtomicTask::ExecuteWithContext().
#define SYSTEM_LOG