diff options
-rw-r--r-- | src/crepe/api/AI.cpp | 46 | ||||
-rw-r--r-- | src/crepe/api/AI.h | 14 | ||||
-rw-r--r-- | src/example/AITest.cpp | 4 |
3 files changed, 62 insertions, 2 deletions
diff --git a/src/crepe/api/AI.cpp b/src/crepe/api/AI.cpp index 49f6b92..00e5b37 100644 --- a/src/crepe/api/AI.cpp +++ b/src/crepe/api/AI.cpp @@ -27,4 +27,50 @@ void AI::make_circle_path(float radius, vec2 center, float start_angle, bool clo } } +void AI::make_oval_path(float radius_x, float radius_y, vec2 center, float start_angle, + bool clockwise, float rotation) { + float max_radius = std::max(radius_x, radius_y); + // The step size is determined by the radius (step size is in radians) + float step = 400.0f / max_radius; + // Force at least 16 steps (in case of a small radius) + if (step > 2 * M_PI / 16) { + step = 2 * M_PI / 16; + } + // The path node distance is determined by the step size and the radius + path_node_distance = max_radius * step * 0.75f; + + auto rotate_point = [rotation](vec2 point, vec2 center) { + float s = sin(rotation); + float c = cos(rotation); + + // Translate point back to origin + point.x -= center.x; + point.y -= center.y; + + // Rotate point + float xnew = point.x * c - point.y * s; + float ynew = point.x * s + point.y * c; + + // Translate point back + point.x = xnew + center.x; + point.y = ynew + center.y; + + return point; + }; + + if (clockwise) { + for (float i = start_angle; i < 2 * M_PI + start_angle; i += step) { + vec2 point = {static_cast<float>(center.x + radius_x * cos(i)), + static_cast<float>(center.y + radius_y * sin(i))}; + path.push_back(rotate_point(point, center)); + } + } else { + for (float i = start_angle; i > start_angle - 2 * M_PI; i -= step) { + vec2 point = {static_cast<float>(center.x + radius_x * cos(i)), + static_cast<float>(center.y + radius_y * sin(i))}; + path.push_back(rotate_point(point, center)); + } + } +} + } // namespace crepe diff --git a/src/crepe/api/AI.h b/src/crepe/api/AI.h index 0dccd5f..c95924d 100644 --- a/src/crepe/api/AI.h +++ b/src/crepe/api/AI.h @@ -81,6 +81,20 @@ public: */ void make_circle_path(float radius, vec2 center = {0, 0}, float start_angle = 0, bool clockwise = true); + /** + * \brief Make an oval path (for the path following behavior) + * + * \note The path is not relative to the entity's position (it is an absolute path) + * + * \param radius_x The x radius of the oval (in game units) + * \param radius_y The y radius of the oval (in game units) + * \param center The center of the oval (in game units) + * \param start_angle The start angle of the oval (in radians) + * \param clockwise The direction of the oval + * \param rotation The rotation of the oval (in radians) + */ + void make_oval_path(float radius_x, float radius_y, vec2 center = {0, 0}, + float start_angle = 0, bool clockwise = true, float rotation = 0); public: //! The maximum force that can be applied to the entity (higher values will make the entity adjust faster) diff --git a/src/example/AITest.cpp b/src/example/AITest.cpp index 28537ed..f4efc9f 100644 --- a/src/example/AITest.cpp +++ b/src/example/AITest.cpp @@ -59,8 +59,8 @@ public: // ai.arrive_on(); // ai.flee_on(); ai.path_follow_on(); - ai.make_circle_path(1000, {0, -1000}, 1.5707, true); - ai.make_circle_path(1000, {0, 1000}, 4.7124, false); + ai.make_oval_path(500, 1000, {0, -1000}, 1.5708, true); + ai.make_oval_path(1000, 500, {0, 500}, 4.7124, false); game_object1.add_component<Rigidbody>(Rigidbody::Data{ .mass = 0.1f, .max_linear_velocity = {40, 40}, |