aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--contributing.md40
-rw-r--r--src/crepe/api/Rigidbody.h44
-rw-r--r--src/crepe/api/Sprite.h10
-rw-r--r--src/crepe/api/Text.cpp2
-rw-r--r--src/crepe/api/Text.h2
-rw-r--r--src/crepe/api/Vector2.h3
-rw-r--r--src/crepe/api/Vector2.hpp5
-rw-r--r--src/crepe/facade/SDLContext.cpp75
-rw-r--r--src/crepe/facade/SDLContext.h23
-rw-r--r--src/crepe/facade/Texture.cpp1
-rw-r--r--src/crepe/system/CollisionSystem.cpp868
-rw-r--r--src/crepe/system/CollisionSystem.h290
-rw-r--r--src/crepe/system/ParticleSystem.cpp6
-rw-r--r--src/crepe/system/RenderSystem.cpp66
-rw-r--r--src/crepe/system/RenderSystem.h30
-rw-r--r--src/crepe/util/AbsolutePosition.cpp20
-rw-r--r--src/crepe/util/AbsolutePosition.h29
-rw-r--r--src/crepe/util/CMakeLists.txt2
-rw-r--r--src/example/game.cpp469
-rw-r--r--src/example/rendering_particle.cpp45
-rw-r--r--src/test/CollisionTest.cpp93
-rw-r--r--src/test/Profiling.cpp6
23 files changed, 1142 insertions, 988 deletions
diff --git a/.gitignore b/.gitignore
index 8bfb819..90dcffe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,4 @@ CTestTestfile.cmake
_deps
CMakeUserPresets.json
compile.sh
+asset/jetpack_joyride
diff --git a/contributing.md b/contributing.md
index 5555892..d217410 100644
--- a/contributing.md
+++ b/contributing.md
@@ -19,6 +19,20 @@ that you can click on to open them.
an explanation as to why the code can not (reliably) be tested
- Non-bugfix pull requests must be approved by at least 2 reviewers before being
merged
+- Pull requests should have the following labels (where appropriate)
+ |label|meaning|
+ |:-:|-|
+ |`fix me`|has feedback that should be resolved/discussed by its author|
+ |`review me`|needs additional reviewers (minimum of 2 per PR)|
+ |`do not review`|is actively being worked on or not ready for feedback|
+ |`high priority`|should be worked on before all the others|
+ - PRs start with the `review me` label
+ - Reviewers—
+ - Add the `fix me` label after adding comments
+ - Authors—
+ - Remove the `review me` label if the pull request has enough reviewers
+ - Add the `do not review` label while processing feedback / pushing
+ additional commits
<!--
- TODO: tagging / versions
@@ -163,40 +177,28 @@ that you can click on to open them.
```
</td></tr></table></details>
- <details><summary>
- <code>using namespace</code> may not be used in header files (.h, .hpp), only
- in source files (.cpp).
+ <a href="https://en.cppreference.com/w/cpp/language/using_declaration">Using-declarations</a>
+ may not be used in header files (<code>.h</code>, <code>.hpp</code>), only in
+ source files (<code>.cpp</code>).
</summary><table><tr><th>Good</th><th>Bad</th></tr><tr><td>
example.h:
```cpp
namespace crepe {
- void foo();
+ std::string foo();
}
```
- example.cpp:
- ```cpp
- #include "example.h"
- using namespace crepe;
- void foo() {}
- ```
</td><td>
example.h:
```cpp
+ using namespace std;
+
namespace crepe {
- template <typename T>
- T foo();
+ string foo();
}
```
-
- example.hpp:
- ```cpp
- #include "example.h"
- using namespace crepe;
- template <typename T>
- T foo();
- ```
</td></tr></table></details>
- <details><summary>
diff --git a/src/crepe/api/Rigidbody.h b/src/crepe/api/Rigidbody.h
index 6900295..b63d941 100644
--- a/src/crepe/api/Rigidbody.h
+++ b/src/crepe/api/Rigidbody.h
@@ -2,6 +2,7 @@
#include <cmath>
#include <set>
+#include <string>
#include "../Component.h"
@@ -120,26 +121,49 @@ public:
* above 0.0.
*
*/
- float elastisity_coefficient = 0.0;
+ float elasticity_coefficient = 0.0;
/**
- * \brief Offset of all colliders relative to the object's transform position.
+ * \brief Enables collision handling for objects colliding with kinematic objects.
+ *
+ * Enables collision handling for objects colliding with kinematic objects in the collision system.
+ * If `kinematic_collision` is true, dynamic objects cannot pass through this kinematic object.
+ * This ensures that kinematic objects delegate collision handling to the collision system.
+ */
+ bool kinematic_collision = true;
+
+ /**
+ * \brief Defines the collision layers a GameObject interacts with.
*
- * The `offset` defines a positional shift applied to all colliders associated with the object, relative to the object's
- * transform position. This allows for the colliders to be placed at a different position than the object's actual
- * position, without modifying the object's transform itself.
+ * The `collision_layers` represent the set of layers the GameObject can detect collisions with.
+ * Each element in this set corresponds to a layer ID. The GameObject will only collide with other
+ * GameObjects that belong to one these layers.
+ */
+ std::set<int> collision_layers = {0};
+
+ /**
+ * \brief Specifies the collision layer of the GameObject.
*
+ * The `collision_layer` indicates the single layer that this GameObject belongs to.
+ * This determines which layers other objects must match to detect collisions with this object.
*/
- vec2 offset;
+ int collision_layer = 0;
/**
* \brief Defines the collision layers of a GameObject.
*
- * The `collision_layers` specifies the layers that the GameObject will collide with.
- * Each element represents a layer ID, and the GameObject will only detect
- * collisions with other GameObjects that belong to these layers.
+ * The `collision_names` specifies where the GameObject will collide with.
+ * Each element represents a name from the Metadata of the gameobject.
*/
- std::set<int> collision_layers = {0};
+ std::set<std::string> collision_names;
+
+ /**
+ * \brief Defines the collision layers of a GameObject.
+ *
+ * The `collision_tags` specifies where the GameObject will collide with.
+ * Each element represents a tag from the Metadata of the gameobject.
+ */
+ std::set<std::string> collision_tags;
};
public:
diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h
index a2409c2..a3fc319 100644
--- a/src/crepe/api/Sprite.h
+++ b/src/crepe/api/Sprite.h
@@ -66,6 +66,16 @@ public:
//! independent sprite offset position
vec2 position_offset;
+
+ /**
+ * \brief gives the user the option to render this in world space or in camera space
+ *
+ * - if true will this be rendered in world space this means that the sprite can be
+ * rendered off the screen
+ * - if false --> will the sprite be rendered in camera space. this means that the
+ * coordinates given on the \c Sprite and \c Transform will be inside the camera
+ */
+ bool world_space = true;
};
public:
diff --git a/src/crepe/api/Text.cpp b/src/crepe/api/Text.cpp
index 54a4370..4a94180 100644
--- a/src/crepe/api/Text.cpp
+++ b/src/crepe/api/Text.cpp
@@ -1,5 +1,3 @@
-#include "../facade/FontFacade.h"
-
#include "Text.h"
using namespace crepe;
diff --git a/src/crepe/api/Text.h b/src/crepe/api/Text.h
index c30dc80..da40141 100644
--- a/src/crepe/api/Text.h
+++ b/src/crepe/api/Text.h
@@ -3,8 +3,6 @@
#include <optional>
#include <string>
-#include "../Component.h"
-
#include "Asset.h"
#include "Color.h"
#include "UIObject.h"
diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h
index bf9d124..52e1bb6 100644
--- a/src/crepe/api/Vector2.h
+++ b/src/crepe/api/Vector2.h
@@ -90,6 +90,9 @@ struct Vector2 {
//! Returns the perpendicular vector to this vector.
Vector2 perpendicular() const;
+
+ //! Checks if both components of the vector are NaN.
+ bool is_nan() const;
};
} // namespace crepe
diff --git a/src/crepe/api/Vector2.hpp b/src/crepe/api/Vector2.hpp
index ff53cb0..e195760 100644
--- a/src/crepe/api/Vector2.hpp
+++ b/src/crepe/api/Vector2.hpp
@@ -163,4 +163,9 @@ Vector2<T> Vector2<T>::perpendicular() const {
return {-y, x};
}
+template <class T>
+bool Vector2<T>::is_nan() const {
+ return std::isnan(x) && std::isnan(y);
+}
+
} // namespace crepe
diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp
index 9486ccd..536ea43 100644
--- a/src/crepe/facade/SDLContext.cpp
+++ b/src/crepe/facade/SDLContext.cpp
@@ -11,7 +11,6 @@
#include <array>
#include <cmath>
#include <cstddef>
-#include <cstdint>
#include <functional>
#include <memory>
#include <stdexcept>
@@ -21,7 +20,11 @@
#include "../api/Config.h"
#include "../api/Sprite.h"
#include "../util/dbg.h"
+#include "api/Text.h"
+#include "api/Transform.h"
+#include "facade/Font.h"
#include "manager/Mediator.h"
+#include "util/AbsolutePosition.h"
#include "SDLContext.h"
#include "Texture.h"
@@ -32,9 +35,6 @@ using namespace std;
SDLContext::SDLContext(Mediator & mediator) {
dbg_trace();
- if (TTF_Init() == -1) {
- throw runtime_error(format("SDL_ttf initialization failed: {}", TTF_GetError()));
- }
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
throw runtime_error(format("SDLContext: SDL_Init error: {}", SDL_GetError()));
}
@@ -63,6 +63,10 @@ SDLContext::SDLContext(Mediator & mediator) {
throw runtime_error("SDLContext: SDL_image could not initialize!");
}
+ if (TTF_Init() == -1) {
+ throw runtime_error(format("SDL_ttf initialization failed: {}", TTF_GetError()));
+ }
+
mediator.sdl_context = *this;
}
@@ -75,8 +79,8 @@ SDLContext::~SDLContext() {
// TODO: how are we going to ensure that these are called from the same
// thread that SDL_Init() was called on? This has caused problems for me
// before.
- IMG_Quit();
TTF_Quit();
+ IMG_Quit();
SDL_Quit();
}
@@ -137,6 +141,8 @@ SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const {
= (ctx.sprite.aspect_ratio == 0) ? ctx.texture.get_ratio() : ctx.sprite.aspect_ratio;
vec2 size = data.size;
+ vec2 screen_pos = ctx.pos;
+
if (data.size.x == 0 && data.size.y != 0) {
size.x = data.size.y * aspect_ratio;
}
@@ -145,10 +151,15 @@ SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const {
}
size *= cam_aux_data.render_scale * ctx.img_scale * data.scale_offset;
- vec2 screen_pos = (ctx.pos + data.position_offset - cam_aux_data.cam_pos
- + (cam_aux_data.zoomed_viewport) / 2)
- * cam_aux_data.render_scale
- - size / 2 + cam_aux_data.bar_size;
+ if (ctx.sprite.data.world_space) {
+ screen_pos = (screen_pos - cam_aux_data.cam_pos + cam_aux_data.zoomed_viewport / 2)
+ * cam_aux_data.render_scale
+ - size / 2 + cam_aux_data.bar_size;
+ } else {
+ screen_pos
+ = (screen_pos + cam_aux_data.zoomed_viewport / 2) * cam_aux_data.render_scale
+ - size / 2 + cam_aux_data.bar_size;
+ }
return SDL_FRect{
.x = screen_pos.x,
@@ -188,6 +199,52 @@ void SDLContext::draw(const RenderContext & ctx) {
angle, NULL, render_flip);
}
+void SDLContext::draw_text(const RenderText & data) {
+
+ const Text & text = data.text;
+ const Font & font = data.font;
+ vec2 absoluut_pos = AbsolutePosition::get_position(data.transform, data.text.offset);
+ std::unique_ptr<SDL_Surface, std::function<void(SDL_Surface *)>> font_surface;
+ std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> font_texture;
+
+ SDL_Color color{
+ .r = text.data.text_color.r,
+ .g = text.data.text_color.g,
+ .b = text.data.text_color.b,
+ .a = text.data.text_color.a,
+ };
+ SDL_Surface * tmp_font_surface
+ = TTF_RenderText_Solid(font.get_font(), text.text.c_str(), color);
+ if (tmp_font_surface == NULL) {
+ throw runtime_error(format("draw_text: font surface error: {}", SDL_GetError()));
+ }
+ font_surface = {tmp_font_surface, [](SDL_Surface * surface) { SDL_FreeSurface(surface); }};
+
+ SDL_Texture * tmp_font_texture
+ = SDL_CreateTextureFromSurface(this->game_renderer.get(), font_surface.get());
+ if (tmp_font_texture == NULL) {
+ throw runtime_error(format("draw_text: font texture error: {}", SDL_GetError()));
+ }
+ font_texture
+ = {tmp_font_texture, [](SDL_Texture * texture) { SDL_DestroyTexture(texture); }};
+
+ vec2 size = text.dimensions * cam_aux_data.render_scale * data.transform.scale;
+ vec2 screen_pos
+ = (absoluut_pos - cam_aux_data.cam_pos + (cam_aux_data.zoomed_viewport) / 2)
+ * cam_aux_data.render_scale
+ - size / 2 + cam_aux_data.bar_size;
+
+ SDL_FRect dstrect{
+ .x = screen_pos.x,
+ .y = screen_pos.y,
+ .w = size.x,
+ .h = size.y,
+ };
+
+ SDL_RenderCopyExF(this->game_renderer.get(), font_texture.get(), NULL, &dstrect,
+ data.transform.rotation, NULL, SDL_FLIP_NONE);
+}
+
void SDLContext::update_camera_view(const Camera & cam, const vec2 & new_pos) {
const Camera::Data & cam_data = cam.data;
diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h
index b687f87..e570073 100644
--- a/src/crepe/facade/SDLContext.h
+++ b/src/crepe/facade/SDLContext.h
@@ -12,18 +12,21 @@
#include <unordered_map>
#include "../types.h"
+#include "EventData.h"
#include "api/Camera.h"
#include "api/Color.h"
#include "api/KeyCodes.h"
#include "api/Sprite.h"
#include "api/Transform.h"
-#include "types.h"
#include "EventData.h"
#include "FontFacade.h"
+#include "types.h"
namespace crepe {
class Texture;
+class Text;
+class Font;
class Mediator;
/**
@@ -71,12 +74,11 @@ public:
const double & scale;
};
-public:
- /**
- * \brief Gets the singleton instance of SDLContext.
- * \return Reference to the SDLContext instance.
- */
- static SDLContext & get_instance();
+ struct RenderText {
+ const Text & text;
+ const Font & font;
+ const Transform & transform;
+ };
public:
SDLContext(const SDLContext &) = delete;
@@ -186,6 +188,13 @@ public:
*/
void draw(const RenderContext & ctx);
+ /**
+ * \brief draws a text to the screen
+ *
+ * \param data Reference to the rendering data needed to draw
+ */
+ void draw_text(const RenderText & data);
+
//! Clears the screen, preparing for a new frame.
void clear_screen();
diff --git a/src/crepe/facade/Texture.cpp b/src/crepe/facade/Texture.cpp
index 6fb22e1..06caa54 100644
--- a/src/crepe/facade/Texture.cpp
+++ b/src/crepe/facade/Texture.cpp
@@ -4,6 +4,7 @@
#include "../types.h"
#include "../util/dbg.h"
+#include "SDLContext.h"
#include "Texture.h"
using namespace crepe;
diff --git a/src/crepe/system/CollisionSystem.cpp b/src/crepe/system/CollisionSystem.cpp
index 9d88d9f..654d4c6 100644
--- a/src/crepe/system/CollisionSystem.cpp
+++ b/src/crepe/system/CollisionSystem.cpp
@@ -1,6 +1,7 @@
#include <algorithm>
#include <cmath>
#include <cstddef>
+#include <emmintrin.h>
#include <functional>
#include <optional>
#include <utility>
@@ -15,13 +16,23 @@
#include "api/Rigidbody.h"
#include "api/Transform.h"
#include "api/Vector2.h"
+#include "util/AbsolutePosition.h"
+#include "util/OptionalRef.h"
-#include "Collider.h"
#include "CollisionSystem.h"
#include "types.h"
-#include "util/OptionalRef.h"
using namespace crepe;
+using enum Rigidbody::BodyType;
+
+CollisionSystem::CollisionInfo CollisionSystem::CollisionInfo::operator-() const {
+ return {
+ .self = this->other,
+ .other = this->self,
+ .resolution = -this->resolution,
+ .resolution_direction = this->resolution_direction,
+ };
+}
void CollisionSystem::fixed_update() {
std::vector<CollisionInternal> all_colliders;
@@ -33,6 +44,7 @@ void CollisionSystem::fixed_update() {
if (!rigidbody.active) continue;
id = rigidbody.game_object_id;
Transform & transform = mgr.get_components_by_id<Transform>(id).front().get();
+ Metadata & metadata = mgr.get_components_by_id<Metadata>(id).front().get();
// Check if the boxcollider is active and has the same id as the rigidbody.
RefVector<BoxCollider> boxcolliders = mgr.get_components_by_type<BoxCollider>();
for (BoxCollider & boxcollider : boxcolliders) {
@@ -40,8 +52,7 @@ void CollisionSystem::fixed_update() {
if (!boxcollider.active) continue;
all_colliders.push_back({.id = id,
.collider = collider_variant{boxcollider},
- .transform = transform,
- .rigidbody = rigidbody});
+ .info = {transform, rigidbody, metadata}});
}
// Check if the circlecollider is active and has the same id as the rigidbody.
RefVector<CircleCollider> circlecolliders
@@ -51,310 +62,450 @@ void CollisionSystem::fixed_update() {
if (!circlecollider.active) continue;
all_colliders.push_back({.id = id,
.collider = collider_variant{circlecollider},
- .transform = transform,
- .rigidbody = rigidbody});
+ .info = {transform, rigidbody, metadata}});
}
}
- // Check between all colliders if there is a collision
+ // Check between all colliders if there is a collision (collision handling)
std::vector<std::pair<CollisionInternal, CollisionInternal>> collided
= this->gather_collisions(all_colliders);
- // For both objects call the collision handler
+ // For the object convert the info and call the collision handler if needed
for (auto & collision_pair : collided) {
- this->collision_handler_request(collision_pair.first, collision_pair.second);
- this->collision_handler_request(collision_pair.second, collision_pair.first);
+ // Convert internal struct to external struct
+ CollisionInfo info
+ = this->get_collision_info(collision_pair.first, collision_pair.second);
+ // Determine if and/or what collison handler is needed.
+ this->determine_collision_handler(info);
}
}
-void CollisionSystem::collision_handler_request(CollisionInternal & this_data,
- CollisionInternal & other_data) {
+// Below is for collision detection
+std::vector<std::pair<CollisionSystem::CollisionInternal, CollisionSystem::CollisionInternal>>
+CollisionSystem::gather_collisions(std::vector<CollisionInternal> & colliders) {
- CollisionInternalType type
- = this->get_collider_type(this_data.collider, other_data.collider);
- std::pair<vec2, CollisionSystem::Direction> resolution_data
- = this->collision_handler(this_data, other_data, type);
- ComponentManager & mgr = this->mediator.component_manager;
- OptionalRef<Metadata> this_metadata
- = mgr.get_components_by_id<Metadata>(this_data.id).front().get();
- OptionalRef<Metadata> other_metadata
- = mgr.get_components_by_id<Metadata>(other_data.id).front().get();
- OptionalRef<Collider> this_collider;
- OptionalRef<Collider> other_collider;
- switch (type) {
- case CollisionInternalType::BOX_BOX: {
- this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider);
- other_collider
- = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
- break;
- }
- case CollisionInternalType::BOX_CIRCLE: {
- this_collider = std::get<std::reference_wrapper<BoxCollider>>(this_data.collider);
- other_collider
- = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
- break;
- }
- case CollisionInternalType::CIRCLE_BOX: {
- this_collider
- = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider);
- other_collider
- = std::get<std::reference_wrapper<BoxCollider>>(other_data.collider);
- break;
- }
- case CollisionInternalType::CIRCLE_CIRCLE: {
- this_collider
- = std::get<std::reference_wrapper<CircleCollider>>(this_data.collider);
- other_collider
- = std::get<std::reference_wrapper<CircleCollider>>(other_data.collider);
- break;
+ // TODO:
+ // If no colliders skip
+ // Check if colliders has rigidbody if not skip
+
+ // TODO:
+ // If amount is higer than lets say 16 for now use quadtree otwerwise skip
+ // Quadtree code
+ // Quadtree is placed over the input vector
+
+ // Return data of collided colliders which are variants
+ std::vector<std::pair<CollisionInternal, CollisionInternal>> collisions_ret;
+ //using visit to visit the variant to access the active and id.
+ for (size_t i = 0; i < colliders.size(); ++i) {
+ for (size_t j = i + 1; j < colliders.size(); ++j) {
+ if (colliders[i].id == colliders[j].id) continue;
+ if (!should_collide(colliders[i], colliders[j])) continue;
+ CollisionInternalType type
+ = get_collider_type(colliders[i].collider, colliders[j].collider);
+ if (!detect_collision(colliders[i], colliders[j], type)) continue;
+ //fet
+ collisions_ret.emplace_back(colliders[i], colliders[j]);
}
}
+ return collisions_ret;
+}
- // collision info
- crepe::CollisionSystem::CollisionInfo collision_info{
- .this_collider = this_collider,
- .this_transform = this_data.transform,
- .this_rigidbody = this_data.rigidbody,
- .this_metadata = this_metadata,
- .other_collider = other_collider,
- .other_transform = other_data.transform,
- .other_rigidbody = other_data.rigidbody,
- .other_metadata = other_metadata,
- .resolution = resolution_data.first,
- .resolution_direction = resolution_data.second,
- };
+bool CollisionSystem::should_collide(const CollisionInternal & self,
+ const CollisionInternal & other) const {
+
+ const Rigidbody::Data & self_rigidbody = self.info.rigidbody.data;
+ const Rigidbody::Data & other_rigidbody = other.info.rigidbody.data;
+ const Metadata & self_metadata = self.info.metadata;
+ const Metadata & other_metadata = other.info.metadata;
+
+ // Check collision layers
+ if (self_rigidbody.collision_layers.contains(other_rigidbody.collision_layer)) return true;
+ if (other_rigidbody.collision_layers.contains(self_rigidbody.collision_layer)) return true;
- // Determine if static needs to be called
- this->determine_collision_handler(collision_info);
+ // Check names
+ if (self_rigidbody.collision_names.contains(other_metadata.name)) return true;
+ if (other_rigidbody.collision_names.contains(self_metadata.name)) return true;
+
+ // Check tags
+ if (self_rigidbody.collision_tags.contains(other_metadata.tag)) return true;
+ if (other_rigidbody.collision_tags.contains(self_metadata.tag)) return true;
+
+ return false;
+}
+
+CollisionSystem::CollisionInternalType
+CollisionSystem::get_collider_type(const collider_variant & collider1,
+ const collider_variant & collider2) const {
+ if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider1)) {
+ if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2)) {
+ return CollisionInternalType::CIRCLE_CIRCLE;
+ } else {
+ return CollisionInternalType::CIRCLE_BOX;
+ }
+ } else {
+ if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2)) {
+ return CollisionInternalType::BOX_CIRCLE;
+ } else {
+ return CollisionInternalType::BOX_BOX;
+ }
+ }
}
-std::pair<vec2, CollisionSystem::Direction>
-CollisionSystem::collision_handler(CollisionInternal & data1, CollisionInternal & data2,
- CollisionInternalType type) {
+bool CollisionSystem::detect_collision(CollisionInternal & self, CollisionInternal & other,
+ const CollisionInternalType & type) {
vec2 resolution;
switch (type) {
case CollisionInternalType::BOX_BOX: {
- const BoxCollider & collider1
- = std::get<std::reference_wrapper<BoxCollider>>(data1.collider);
- const BoxCollider & collider2
- = std::get<std::reference_wrapper<BoxCollider>>(data2.collider);
- vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform,
- data1.rigidbody);
- vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform,
- data2.rigidbody);
- resolution = this->get_box_box_resolution(collider1, collider2, collider_pos1,
- collider_pos2);
+ // Box-Box collision detection
+ const BoxColliderInternal BOX1
+ = {.collider = std::get<std::reference_wrapper<BoxCollider>>(self.collider),
+ .transform = self.info.transform,
+ .rigidbody = self.info.rigidbody};
+ const BoxColliderInternal BOX2
+ = {.collider = std::get<std::reference_wrapper<BoxCollider>>(other.collider),
+ .transform = other.info.transform,
+ .rigidbody = other.info.rigidbody};
+ // Get resolution vector from box-box collision detection
+ resolution = this->get_box_box_detection(BOX1, BOX2);
+ // If no collision (NaN values), return false
+ if (resolution.is_nan()) return false;
break;
}
case CollisionInternalType::BOX_CIRCLE: {
- const BoxCollider & collider1
- = std::get<std::reference_wrapper<BoxCollider>>(data1.collider);
- const CircleCollider & collider2
- = std::get<std::reference_wrapper<CircleCollider>>(data2.collider);
- vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform,
- data1.rigidbody);
- vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform,
- data2.rigidbody);
- resolution = -this->get_circle_box_resolution(collider2, collider1, collider_pos2,
- collider_pos1);
+ // Box-Circle collision detection
+ const BoxColliderInternal BOX1
+ = {.collider = std::get<std::reference_wrapper<BoxCollider>>(self.collider),
+ .transform = self.info.transform,
+ .rigidbody = self.info.rigidbody};
+ const CircleColliderInternal CIRCLE2 = {
+ .collider = std::get<std::reference_wrapper<CircleCollider>>(other.collider),
+ .transform = other.info.transform,
+ .rigidbody = other.info.rigidbody};
+ // Get resolution vector from box-circle collision detection
+ resolution = this->get_box_circle_detection(BOX1, CIRCLE2);
+ // If no collision (NaN values), return false
+ if (resolution.is_nan()) return false;
+ // Invert the resolution vector for proper collision response
+ resolution = -resolution;
break;
}
case CollisionInternalType::CIRCLE_CIRCLE: {
- const CircleCollider & collider1
- = std::get<std::reference_wrapper<CircleCollider>>(data1.collider);
- const CircleCollider & collider2
- = std::get<std::reference_wrapper<CircleCollider>>(data2.collider);
- vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform,
- data1.rigidbody);
- vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform,
- data2.rigidbody);
- resolution = this->get_circle_circle_resolution(collider1, collider2,
- collider_pos1, collider_pos2);
+ // Circle-Circle collision detection
+ const CircleColliderInternal CIRCLE1
+ = {.collider = std::get<std::reference_wrapper<CircleCollider>>(self.collider),
+ .transform = self.info.transform,
+ .rigidbody = self.info.rigidbody};
+ const CircleColliderInternal CIRCLE2 = {
+ .collider = std::get<std::reference_wrapper<CircleCollider>>(other.collider),
+ .transform = other.info.transform,
+ .rigidbody = other.info.rigidbody};
+ // Get resolution vector from circle-circle collision detection
+ resolution = this->get_circle_circle_detection(CIRCLE1, CIRCLE2);
+ // If no collision (NaN values), return false
+ if (resolution.is_nan()) return false;
break;
}
case CollisionInternalType::CIRCLE_BOX: {
- const CircleCollider & collider1
- = std::get<std::reference_wrapper<CircleCollider>>(data1.collider);
- const BoxCollider & collider2
- = std::get<std::reference_wrapper<BoxCollider>>(data2.collider);
- vec2 collider_pos1 = this->get_current_position(collider1.offset, data1.transform,
- data1.rigidbody);
- vec2 collider_pos2 = this->get_current_position(collider2.offset, data2.transform,
- data2.rigidbody);
- resolution = this->get_circle_box_resolution(collider1, collider2, collider_pos1,
- collider_pos2);
+ // Circle-Box collision detection
+ const CircleColliderInternal CIRCLE1
+ = {.collider = std::get<std::reference_wrapper<CircleCollider>>(self.collider),
+ .transform = self.info.transform,
+ .rigidbody = self.info.rigidbody};
+ const BoxColliderInternal BOX2
+ = {.collider = std::get<std::reference_wrapper<BoxCollider>>(other.collider),
+ .transform = other.info.transform,
+ .rigidbody = other.info.rigidbody};
+ // Get resolution vector from box-circle collision detection (order swapped)
+ resolution = this->get_box_circle_detection(BOX2, CIRCLE1);
+ // If no collision (NaN values), return false
+ if (resolution.is_nan()) return false;
break;
}
+ case CollisionInternalType::NONE:
+ // No collision detection needed if the type is NONE
+ return false;
+ break;
}
+ // Store the calculated resolution vector for the 'self' collider
+ self.resolution = resolution;
+ // Calculate the resolution direction based on the rigidbody data
+ self.resolution_direction
+ = this->resolution_correction(self.resolution, self.info.rigidbody.data);
+ // For the 'other' collider, the resolution is the opposite direction of 'self'
+ other.resolution = -self.resolution;
+ other.resolution_direction = self.resolution_direction;
+
+ // Return true if a collision was detected and resolution was calculated
+ return true;
+}
- Direction resolution_direction = Direction::NONE;
- if (resolution.x != 0 && resolution.y != 0) {
- resolution_direction = Direction::BOTH;
- } else if (resolution.x != 0) {
- resolution_direction = Direction::X_DIRECTION;
- //checks if the other velocity has a value and if this object moved
- if (data1.rigidbody.data.linear_velocity.x != 0
- && data1.rigidbody.data.linear_velocity.y != 0)
- resolution.y = -data1.rigidbody.data.linear_velocity.y
- * (resolution.x / data1.rigidbody.data.linear_velocity.x);
- } else if (resolution.y != 0) {
- resolution_direction = Direction::Y_DIRECTION;
- //checks if the other velocity has a value and if this object moved
- if (data1.rigidbody.data.linear_velocity.x != 0
- && data1.rigidbody.data.linear_velocity.y != 0)
- resolution.x = -data1.rigidbody.data.linear_velocity.x
- * (resolution.y / data1.rigidbody.data.linear_velocity.y);
- }
+vec2 CollisionSystem::get_box_box_detection(const BoxColliderInternal & box1,
+ const BoxColliderInternal & box2) const {
+ vec2 resolution{NAN, NAN};
+ // Get current positions of colliders
+ vec2 pos1 = AbsolutePosition::get_position(box1.transform, box1.collider.offset);
+ vec2 pos2 = AbsolutePosition::get_position(box2.transform, box2.collider.offset);
- return std::make_pair(resolution, resolution_direction);
-}
+ // Scale dimensions
+ vec2 scaled_box1 = box1.collider.dimensions * box1.transform.scale;
+ vec2 scaled_box2 = box2.collider.dimensions * box2.transform.scale;
+ vec2 delta = pos2 - pos1;
-vec2 CollisionSystem::get_box_box_resolution(const BoxCollider & box_collider1,
- const BoxCollider & box_collider2,
- const vec2 & final_position1,
- const vec2 & final_position2) const {
- vec2 resolution; // Default resolution vector
- vec2 delta = final_position2 - final_position1;
-
- // Compute half-dimensions of the boxes
- float half_width1 = box_collider1.dimensions.x / 2.0;
- float half_height1 = box_collider1.dimensions.y / 2.0;
- float half_width2 = box_collider2.dimensions.x / 2.0;
- float half_height2 = box_collider2.dimensions.y / 2.0;
-
- // Calculate overlaps along X and Y axes
- float overlap_x = (half_width1 + half_width2) - std::abs(delta.x);
- float overlap_y = (half_height1 + half_height2) - std::abs(delta.y);
-
- // Check if there is a collision should always be true
- if (overlap_x > 0 && overlap_y > 0) {
- // Determine the direction of resolution
- if (overlap_x < overlap_y) {
- // Resolve along the X-axis (smallest overlap)
- resolution.x = (delta.x > 0) ? -overlap_x : overlap_x;
- } else if (overlap_y < overlap_x) {
- // Resolve along the Y-axis (smallest overlap)
- resolution.y = (delta.y > 0) ? -overlap_y : overlap_y;
- } else {
- // Equal overlap, resolve both directions with preference
- resolution.x = (delta.x > 0) ? -overlap_x : overlap_x;
- resolution.y = (delta.y > 0) ? -overlap_y : overlap_y;
+ // Calculate half-extents (half width and half height)
+ float half_width1 = scaled_box1.x / 2.0;
+ float half_height1 = scaled_box1.y / 2.0;
+ float half_width2 = scaled_box2.x / 2.0;
+ float half_height2 = scaled_box2.y / 2.0;
+
+ if (pos1.x + half_width1 > pos2.x - half_width2
+ && pos1.x - half_width1 < pos2.x + half_width2
+ && pos1.y + half_height1 > pos2.y - half_height2
+ && pos1.y - half_height1 < pos2.y + half_height2) {
+ resolution = {0, 0};
+ float overlap_x = (half_width1 + half_width2) - std::abs(delta.x);
+ float overlap_y = (half_height1 + half_height2) - std::abs(delta.y);
+ if (overlap_x > 0 && overlap_y > 0) {
+ // Determine the direction of resolution
+ if (overlap_x < overlap_y) {
+ // Resolve along the X-axis (smallest overlap)
+ resolution.x = (delta.x > 0) ? -overlap_x : overlap_x;
+ } else if (overlap_y < overlap_x) {
+ // Resolve along the Y-axis (smallest overlap)
+ resolution.y = (delta.y > 0) ? -overlap_y : overlap_y;
+ } else {
+ // Equal overlap, resolve both directions with preference
+ resolution.x = (delta.x > 0) ? -overlap_x : overlap_x;
+ resolution.y = (delta.y > 0) ? -overlap_y : overlap_y;
+ }
}
}
-
return resolution;
}
-vec2 CollisionSystem::get_circle_circle_resolution(const CircleCollider & circle_collider1,
- const CircleCollider & circle_collider2,
- const vec2 & final_position1,
- const vec2 & final_position2) const {
- vec2 delta = final_position2 - final_position1;
+vec2 CollisionSystem::get_box_circle_detection(const BoxColliderInternal & box,
+ const CircleColliderInternal & circle) const {
+ /// Get current positions of colliders
+ vec2 box_pos = AbsolutePosition::get_position(box.transform, box.collider.offset);
+ vec2 circle_pos = AbsolutePosition::get_position(circle.transform, circle.collider.offset);
- // Compute the distance between the two circle centers
- float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y);
+ // Scale dimensions
+ vec2 scaled_box = box.collider.dimensions * box.transform.scale;
+ float scaled_circle_radius = circle.collider.radius * circle.transform.scale;
- // Compute the combined radii of the two circles
- float combined_radius = circle_collider1.radius + circle_collider2.radius;
+ // Calculate box half-extents
+ float half_width = scaled_box.x / 2.0f;
+ float half_height = scaled_box.y / 2.0f;
- // Compute the penetration depth
- float penetration_depth = combined_radius - distance;
+ // Find the closest point on the box to the circle's center
+ float closest_x
+ = std::max(box_pos.x - half_width, std::min(circle_pos.x, box_pos.x + half_width));
+ float closest_y
+ = std::max(box_pos.y - half_height, std::min(circle_pos.y, box_pos.y + half_height));
- // Normalize the delta vector to get the collision direction
- vec2 collision_normal = delta / distance;
+ float distance_x = circle_pos.x - closest_x;
+ float distance_y = circle_pos.y - closest_y;
+ float distance_squared = distance_x * distance_x + distance_y * distance_y;
+ if (distance_squared < scaled_circle_radius * scaled_circle_radius) {
+ vec2 delta = circle_pos - box_pos;
- // Compute the resolution vector
- vec2 resolution = -collision_normal * penetration_depth;
+ // Clamp circle center to the nearest point on the box
+ vec2 closest_point;
+ closest_point.x = std::clamp(delta.x, -half_width, half_width);
+ closest_point.y = std::clamp(delta.y, -half_height, half_height);
- return resolution;
+ // Find the vector from the circle center to the closest point
+ vec2 closest_delta = delta - closest_point;
+
+ float distance
+ = std::sqrt(closest_delta.x * closest_delta.x + closest_delta.y * closest_delta.y);
+ vec2 collision_normal = closest_delta / distance;
+
+ // Compute penetration depth
+ float penetration_depth = scaled_circle_radius - distance;
+
+ // Compute the resolution vector
+ return vec2{collision_normal * penetration_depth};
+ }
+ // No collision
+ return vec2{NAN, NAN};
}
-vec2 CollisionSystem::get_circle_box_resolution(const CircleCollider & circle_collider,
- const BoxCollider & box_collider,
- const vec2 & circle_position,
- const vec2 & box_position) const {
- vec2 delta = circle_position - box_position;
+vec2 CollisionSystem::get_circle_circle_detection(
+ const CircleColliderInternal & circle1, const CircleColliderInternal & circle2) const {
+ // Get current positions of colliders
+ vec2 final_position1
+ = AbsolutePosition::get_position(circle1.transform, circle1.collider.offset);
+ vec2 final_position2
+ = AbsolutePosition::get_position(circle2.transform, circle2.collider.offset);
- // Compute half-dimensions of the box
- float half_width = box_collider.dimensions.x / 2.0f;
- float half_height = box_collider.dimensions.y / 2.0f;
+ // Scale dimensions
+ float scaled_circle1 = circle1.collider.radius * circle1.transform.scale;
+ float scaled_circle2 = circle2.collider.radius * circle2.transform.scale;
- // Clamp circle center to the nearest point on the box
- vec2 closest_point;
- closest_point.x = std::clamp(delta.x, -half_width, half_width);
- closest_point.y = std::clamp(delta.y, -half_height, half_height);
+ float distance_x = final_position1.x - final_position2.x;
+ float distance_y = final_position1.y - final_position2.y;
+ float distance_squared = distance_x * distance_x + distance_y * distance_y;
- // Find the vector from the circle center to the closest point
- vec2 closest_delta = delta - closest_point;
+ // Calculate the sum of the radii
+ float radius_sum = scaled_circle1 + scaled_circle2;
- // Normalize the delta to get the collision direction
- float distance
- = std::sqrt(closest_delta.x * closest_delta.x + closest_delta.y * closest_delta.y);
- vec2 collision_normal = closest_delta / distance;
+ // Check for collision (distance squared must be less than the square of the radius sum)
+ if (distance_squared < radius_sum * radius_sum) {
+ vec2 delta = final_position2 - final_position1;
- // Compute penetration depth
- float penetration_depth = circle_collider.radius - distance;
+ // Compute the distance between the two circle centers
+ float distance = std::sqrt(delta.x * delta.x + delta.y * delta.y);
- // Compute the resolution vector
- vec2 resolution = collision_normal * penetration_depth;
+ // Compute the combined radii of the two circles
+ float combined_radius = scaled_circle1 + scaled_circle2;
- return resolution;
+ // Compute the penetration depth
+ float penetration_depth = combined_radius - distance;
+
+ // Normalize the delta vector to get the collision direction
+ vec2 collision_normal = delta / distance;
+
+ // Compute the resolution vector
+ vec2 resolution = -collision_normal * penetration_depth;
+
+ return resolution;
+ }
+ // No collision
+ return vec2{NAN, NAN};
+ ;
}
-void CollisionSystem::determine_collision_handler(CollisionInfo & info) {
- // Check rigidbody type for static
- if (info.this_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) return;
- // If second body is static perform the static collision handler in this system
- if (info.other_rigidbody.data.body_type == Rigidbody::BodyType::STATIC) {
- this->static_collision_handler(info);
+CollisionSystem::Direction
+CollisionSystem::resolution_correction(vec2 & resolution, const Rigidbody::Data & rigidbody) {
+
+ // Calculate the other value to move back correctly
+ // If only X or Y has a value determine what is should be to move back.
+ Direction resolution_direction = Direction::NONE;
+ // If both are not zero a perfect corner has been hit
+ if (resolution.x != 0 && resolution.y != 0) {
+ resolution_direction = Direction::BOTH;
+ // If x is not zero a horizontal action was latest action.
+ } else if (resolution.x != 0) {
+ resolution_direction = Direction::X_DIRECTION;
+ // If both are 0 resolution y should not be changed (y_velocity can be 0 by kinematic object movement)
+ if (rigidbody.linear_velocity.x != 0 && rigidbody.linear_velocity.y != 0)
+ resolution.y
+ = -rigidbody.linear_velocity.y * (resolution.x / rigidbody.linear_velocity.x);
+ } else if (resolution.y != 0) {
+ resolution_direction = Direction::Y_DIRECTION;
+ // If both are 0 resolution x should not be changed (x_velocity can be 0 by kinematic object movement)
+ if (rigidbody.linear_velocity.x != 0 && rigidbody.linear_velocity.y != 0)
+ resolution.x
+ = -rigidbody.linear_velocity.x * (resolution.y / rigidbody.linear_velocity.y);
+ }
+
+ return resolution_direction;
+}
+
+CollisionSystem::CollisionInfo
+CollisionSystem::get_collision_info(const CollisionInternal & in_self,
+ const CollisionInternal & in_other) const {
+
+ crepe::CollisionSystem::ColliderInfo self{
+ .transform = in_self.info.transform,
+ .rigidbody = in_self.info.rigidbody,
+ .metadata = in_self.info.metadata,
};
- // Call collision event for user
- CollisionEvent data(info);
- EventManager & emgr = this->mediator.event_manager;
- emgr.trigger_event<CollisionEvent>(data, info.this_collider.game_object_id);
+
+ crepe::CollisionSystem::ColliderInfo other{
+ .transform = in_other.info.transform,
+ .rigidbody = in_other.info.rigidbody,
+ .metadata = in_other.info.metadata,
+ };
+
+ struct CollisionInfo collision_info {
+ .self = self, .other = other, .resolution = in_self.resolution,
+ .resolution_direction = in_self.resolution_direction,
+ };
+ return collision_info;
}
-void CollisionSystem::static_collision_handler(CollisionInfo & info) {
+void CollisionSystem::determine_collision_handler(const CollisionInfo & info) {
+ Rigidbody::BodyType self_type = info.self.rigidbody.data.body_type;
+ Rigidbody::BodyType other_type = info.other.rigidbody.data.body_type;
+ bool self_kinematic = info.self.rigidbody.data.kinematic_collision;
+ bool other_kinematic = info.other.rigidbody.data.kinematic_collision;
+ // Inverted collision info
+ CollisionInfo inverted = -info;
+ // If both objects are static skip handle call collision script
+ if (self_type == STATIC && other_type == STATIC) return;
+
+ // First body is not dynamic
+ if (self_type != DYNAMIC) {
+ bool static_collision = self_type == STATIC && other_type == DYNAMIC;
+ bool kinematic_collision
+ = self_type == KINEMATIC && other_type == DYNAMIC && self_kinematic;
+
+ // Handle collision
+ if (static_collision || kinematic_collision) this->static_collision_handler(inverted);
+ // Call scripts
+ this->call_collision_events(inverted);
+ return;
+ }
+
+ // Second body is not dynamic
+ if (other_type != DYNAMIC) {
+ bool static_collision = other_type == STATIC;
+ bool kinematic_collision = other_type == KINEMATIC && other_kinematic;
+ // Handle collision
+ if (static_collision || kinematic_collision) this->static_collision_handler(info);
+ // Call scripts
+ this->call_collision_events(info);
+ return;
+ }
+
+ // Dynamic
+ // Handle collision
+ this->dynamic_collision_handler(info);
+ // Call scripts
+ this->call_collision_events(info);
+}
+
+void CollisionSystem::static_collision_handler(const CollisionInfo & info) {
+
+ vec2 & transform_pos = info.self.transform.position;
+ float elasticity = info.self.rigidbody.data.elasticity_coefficient;
+ vec2 & rigidbody_vel = info.self.rigidbody.data.linear_velocity;
+
// Move object back using calculate move back value
- info.this_transform.position += info.resolution;
+ transform_pos += info.resolution;
switch (info.resolution_direction) {
case Direction::BOTH:
//bounce
- if (info.this_rigidbody.data.elastisity_coefficient > 0) {
- info.this_rigidbody.data.linear_velocity
- = -info.this_rigidbody.data.linear_velocity
- * info.this_rigidbody.data.elastisity_coefficient;
+ if (elasticity > 0) {
+ rigidbody_vel = -rigidbody_vel * elasticity;
}
//stop movement
else {
- info.this_rigidbody.data.linear_velocity = {0, 0};
+ rigidbody_vel = {0, 0};
}
break;
case Direction::Y_DIRECTION:
// Bounce
- if (info.this_rigidbody.data.elastisity_coefficient > 0) {
- info.this_rigidbody.data.linear_velocity.y
- = -info.this_rigidbody.data.linear_velocity.y
- * info.this_rigidbody.data.elastisity_coefficient;
+ if (elasticity > 0) {
+ rigidbody_vel.y = -rigidbody_vel.y * elasticity;
}
// Stop movement
else {
- info.this_rigidbody.data.linear_velocity.y = 0;
- info.this_transform.position.x -= info.resolution.x;
+ rigidbody_vel.y = 0;
+ transform_pos.x -= info.resolution.x;
}
break;
case Direction::X_DIRECTION:
// Bounce
- if (info.this_rigidbody.data.elastisity_coefficient > 0) {
- info.this_rigidbody.data.linear_velocity.x
- = -info.this_rigidbody.data.linear_velocity.x
- * info.this_rigidbody.data.elastisity_coefficient;
+ if (elasticity > 0) {
+ rigidbody_vel.x = -rigidbody_vel.x * elasticity;
}
// Stop movement
else {
- info.this_rigidbody.data.linear_velocity.x = 0;
- info.this_transform.position.y -= info.resolution.y;
+ rigidbody_vel.x = 0;
+ transform_pos.y -= info.resolution.y;
}
break;
case Direction::NONE:
@@ -363,213 +514,80 @@ void CollisionSystem::static_collision_handler(CollisionInfo & info) {
}
}
-std::vector<std::pair<CollisionSystem::CollisionInternal, CollisionSystem::CollisionInternal>>
-CollisionSystem::gather_collisions(std::vector<CollisionInternal> & colliders) {
-
- // TODO:
- // If no colliders skip
- // Check if colliders has rigidbody if not skip
-
- // TODO:
- // If amount is higer than lets say 16 for now use quadtree otwerwise skip
- // Quadtree code
- // Quadtree is placed over the input vector
+void CollisionSystem::dynamic_collision_handler(const CollisionInfo & info) {
- // Return data of collided colliders which are variants
- std::vector<std::pair<CollisionInternal, CollisionInternal>> collisions_ret;
- //using visit to visit the variant to access the active and id.
- for (size_t i = 0; i < colliders.size(); ++i) {
- for (size_t j = i + 1; j < colliders.size(); ++j) {
- if (colliders[i].id == colliders[j].id) continue;
- if (!have_common_layer(colliders[i].rigidbody.data.collision_layers,
- colliders[j].rigidbody.data.collision_layers))
- continue;
- CollisionInternalType type
- = get_collider_type(colliders[i].collider, colliders[j].collider);
- if (!get_collision(
- {
- .collider = colliders[i].collider,
- .transform = colliders[i].transform,
- .rigidbody = colliders[i].rigidbody,
- },
- {
- .collider = colliders[j].collider,
- .transform = colliders[j].transform,
- .rigidbody = colliders[j].rigidbody,
- },
- type))
- continue;
- collisions_ret.emplace_back(colliders[i], colliders[j]);
- }
- }
+ vec2 & self_transform_pos = info.self.transform.position;
+ vec2 & other_transform_pos = info.other.transform.position;
+ float self_elasticity = info.self.rigidbody.data.elasticity_coefficient;
+ float other_elasticity = info.other.rigidbody.data.elasticity_coefficient;
+ vec2 & self_rigidbody_vel = info.self.rigidbody.data.linear_velocity;
+ vec2 & other_rigidbody_vel = info.other.rigidbody.data.linear_velocity;
- return collisions_ret;
-}
+ self_transform_pos += info.resolution / 2;
+ other_transform_pos += -(info.resolution / 2);
-bool CollisionSystem::have_common_layer(const std::set<int> & layers1,
- const std::set<int> & layers2) {
+ switch (info.resolution_direction) {
+ case Direction::BOTH:
+ if (self_elasticity > 0) {
+ self_rigidbody_vel = -self_rigidbody_vel * self_elasticity;
+ } else {
+ self_rigidbody_vel = {0, 0};
+ }
- // Check if any number is equal in the layers
- for (int num : layers1) {
- if (layers2.contains(num)) {
- // Common layer found
- return true;
+ if (other_elasticity > 0) {
+ other_rigidbody_vel = -other_rigidbody_vel * other_elasticity;
+ } else {
+ other_rigidbody_vel = {0, 0};
+ }
break;
- }
- }
- // No common layer found
- return false;
-}
+ case Direction::Y_DIRECTION:
+ if (self_elasticity > 0) {
+ self_rigidbody_vel.y = -self_rigidbody_vel.y * self_elasticity;
+ }
+ // Stop movement
+ else {
+ self_rigidbody_vel.y = 0;
+ self_transform_pos.x -= info.resolution.x;
+ }
-CollisionSystem::CollisionInternalType
-CollisionSystem::get_collider_type(const collider_variant & collider1,
- const collider_variant & collider2) const {
- if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider1)) {
- if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2)) {
- return CollisionInternalType::CIRCLE_CIRCLE;
- } else {
- return CollisionInternalType::CIRCLE_BOX;
- }
- } else {
- if (std::holds_alternative<std::reference_wrapper<CircleCollider>>(collider2)) {
- return CollisionInternalType::BOX_CIRCLE;
- } else {
- return CollisionInternalType::BOX_BOX;
- }
- }
-}
+ if (other_elasticity > 0) {
+ other_rigidbody_vel.y = -other_rigidbody_vel.y * other_elasticity;
+ }
+ // Stop movement
+ else {
+ other_rigidbody_vel.y = 0;
+ other_transform_pos.x -= info.resolution.x;
+ }
+ break;
+ case Direction::X_DIRECTION:
+ if (self_elasticity > 0) {
+ self_rigidbody_vel.x = -self_rigidbody_vel.x * self_elasticity;
+ }
+ // Stop movement
+ else {
+ self_rigidbody_vel.x = 0;
+ self_transform_pos.y -= info.resolution.y;
+ }
-bool CollisionSystem::get_collision(const CollisionInternal & first_info,
- const CollisionInternal & second_info,
- CollisionInternalType type) const {
- switch (type) {
- case CollisionInternalType::BOX_BOX: {
- const BoxCollider & box_collider1
- = std::get<std::reference_wrapper<BoxCollider>>(first_info.collider);
- const BoxCollider & box_collider2
- = std::get<std::reference_wrapper<BoxCollider>>(second_info.collider);
- return this->get_box_box_collision(box_collider1, box_collider2,
- first_info.transform, second_info.transform,
- second_info.rigidbody, second_info.rigidbody);
- }
- case CollisionInternalType::BOX_CIRCLE: {
- const BoxCollider & box_collider
- = std::get<std::reference_wrapper<BoxCollider>>(first_info.collider);
- const CircleCollider & circle_collider
- = std::get<std::reference_wrapper<CircleCollider>>(second_info.collider);
- return this->get_box_circle_collision(
- box_collider, circle_collider, first_info.transform, second_info.transform,
- second_info.rigidbody, second_info.rigidbody);
- }
- case CollisionInternalType::CIRCLE_CIRCLE: {
- const CircleCollider & circle_collider1
- = std::get<std::reference_wrapper<CircleCollider>>(first_info.collider);
- const CircleCollider & circle_collider2
- = std::get<std::reference_wrapper<CircleCollider>>(second_info.collider);
- return this->get_circle_circle_collision(
- circle_collider1, circle_collider2, first_info.transform,
- second_info.transform, second_info.rigidbody, second_info.rigidbody);
- }
- case CollisionInternalType::CIRCLE_BOX: {
- const CircleCollider & circle_collider
- = std::get<std::reference_wrapper<CircleCollider>>(first_info.collider);
- const BoxCollider & box_collider
- = std::get<std::reference_wrapper<BoxCollider>>(second_info.collider);
- return this->get_box_circle_collision(
- box_collider, circle_collider, first_info.transform, second_info.transform,
- second_info.rigidbody, second_info.rigidbody);
- }
+ if (other_elasticity > 0) {
+ other_rigidbody_vel.x = -other_rigidbody_vel.x * other_elasticity;
+ }
+ // Stop movement
+ else {
+ other_rigidbody_vel.x = 0;
+ other_transform_pos.y -= info.resolution.y;
+ }
+ break;
+ case Direction::NONE:
+ // Not possible
+ break;
}
- return false;
}
-bool CollisionSystem::get_box_box_collision(const BoxCollider & box1, const BoxCollider & box2,
- const Transform & transform1,
- const Transform & transform2,
- const Rigidbody & rigidbody1,
- const Rigidbody & rigidbody2) const {
- // Get current positions of colliders
- vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1);
- vec2 final_position2 = this->get_current_position(box2.offset, transform2, rigidbody2);
-
- // Calculate half-extents (half width and half height)
- float half_width1 = box1.dimensions.x / 2.0;
- float half_height1 = box1.dimensions.y / 2.0;
- float half_width2 = box2.dimensions.x / 2.0;
- float half_height2 = box2.dimensions.y / 2.0;
-
- // Check if the boxes overlap along the X and Y axes
- return (final_position1.x + half_width1 > final_position2.x - half_width2
- && final_position1.x - half_width1 < final_position2.x + half_width2
- && final_position1.y + half_height1 > final_position2.y - half_height2
- && final_position1.y - half_height1 < final_position2.y + half_height2);
-}
-
-bool CollisionSystem::get_box_circle_collision(const BoxCollider & box1,
- const CircleCollider & circle2,
- const Transform & transform1,
- const Transform & transform2,
- const Rigidbody & rigidbody1,
- const Rigidbody & rigidbody2) const {
- // Get current positions of colliders
- vec2 final_position1 = this->get_current_position(box1.offset, transform1, rigidbody1);
- vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2);
-
- // Calculate box half-extents
- float half_width = box1.dimensions.x / 2.0;
- float half_height = box1.dimensions.y / 2.0;
-
- // Find the closest point on the box to the circle's center
- float closest_x = std::max(final_position1.x - half_width,
- std::min(final_position2.x, final_position1.x + half_width));
- float closest_y = std::max(final_position1.y - half_height,
- std::min(final_position2.y, final_position1.y + half_height));
-
- // Calculate the distance squared between the circle's center and the closest point on the box
- float distance_x = final_position2.x - closest_x;
- float distance_y = final_position2.y - closest_y;
- float distance_squared = distance_x * distance_x + distance_y * distance_y;
-
- // Compare distance squared with the square of the circle's radius
- return distance_squared < circle2.radius * circle2.radius;
-}
-
-bool CollisionSystem::get_circle_circle_collision(const CircleCollider & circle1,
- const CircleCollider & circle2,
- const Transform & transform1,
- const Transform & transform2,
- const Rigidbody & rigidbody1,
- const Rigidbody & rigidbody2) const {
- // Get current positions of colliders
- vec2 final_position1 = this->get_current_position(circle1.offset, transform1, rigidbody1);
- vec2 final_position2 = this->get_current_position(circle2.offset, transform2, rigidbody2);
-
- float distance_x = final_position1.x - final_position2.x;
- float distance_y = final_position1.y - final_position2.y;
- float distance_squared = distance_x * distance_x + distance_y * distance_y;
-
- // Calculate the sum of the radii
- float radius_sum = circle1.radius + circle2.radius;
-
- // Check if the distance between the centers is less than or equal to the sum of the radii
- return distance_squared < radius_sum * radius_sum;
-}
-
-vec2 CollisionSystem::get_current_position(const vec2 & collider_offset,
- const Transform & transform,
- const Rigidbody & rigidbody) const {
- // Get the rotation in radians
- float radians1 = transform.rotation * (M_PI / 180.0);
-
- // Calculate total offset with scale
- vec2 total_offset = (rigidbody.data.offset + collider_offset) * transform.scale;
-
- // Rotate
- float rotated_total_offset_x1
- = total_offset.x * cos(radians1) - total_offset.y * sin(radians1);
- float rotated_total_offset_y1
- = total_offset.x * sin(radians1) + total_offset.y * cos(radians1);
-
- // Final positions considering scaling and rotation
- return (transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1));
+void CollisionSystem::call_collision_events(const CollisionInfo & info) {
+ CollisionEvent data(info);
+ CollisionEvent data_inverted(-info);
+ EventManager & emgr = this->mediator.event_manager;
+ emgr.trigger_event<CollisionEvent>(data, info.self.transform.game_object_id);
+ emgr.trigger_event<CollisionEvent>(data_inverted, info.other.transform.game_object_id);
}
diff --git a/src/crepe/system/CollisionSystem.h b/src/crepe/system/CollisionSystem.h
index 48a8f86..3fb9723 100644
--- a/src/crepe/system/CollisionSystem.h
+++ b/src/crepe/system/CollisionSystem.h
@@ -23,6 +23,42 @@ public:
using System::System;
private:
+ //! Enum representing movement directions during collision resolution.
+ enum class Direction {
+ //! No movement required.
+ NONE,
+ //! Movement in the X direction.
+ X_DIRECTION,
+ //! Movement in the Y direction.
+ Y_DIRECTION,
+ //! Movement in both X and Y directions.
+ BOTH,
+ };
+
+public:
+ //! Structure representing components of the collider
+ struct ColliderInfo {
+ Transform & transform;
+ Rigidbody & rigidbody;
+ Metadata & metadata;
+ };
+
+ /**
+ * \brief Structure representing detailed collision information between two colliders.
+ *
+ * Includes information about the colliding objects and the resolution data for handling the collision.
+ */
+ struct CollisionInfo {
+ ColliderInfo self;
+ ColliderInfo other;
+ //! The resolution vector for the collision.
+ vec2 resolution;
+ //! The direction of movement for resolving the collision.
+ Direction resolution_direction = Direction::NONE;
+ CollisionInfo operator-() const;
+ };
+
+private:
//! A variant type that can hold either a BoxCollider or a CircleCollider.
using collider_variant = std::variant<std::reference_wrapper<BoxCollider>,
std::reference_wrapper<CircleCollider>>;
@@ -33,12 +69,13 @@ private:
CIRCLE_CIRCLE,
BOX_CIRCLE,
CIRCLE_BOX,
+ NONE,
};
/**
* \brief A structure to store the collision data of a single collider.
*
- * This structure all components and id that are for needed within this system when calculating or handeling collisions.
+ * This structure all components and id that are for needed within this system when calculating or handling collisions.
* The transform and rigidbody are mostly needed for location and rotation.
* In rigidbody additional info is written about what the body of the object is,
* and how it should respond on a collision.
@@ -46,43 +83,23 @@ private:
struct CollisionInternal {
game_object_id_t id = 0;
collider_variant collider;
- Transform & transform;
- Rigidbody & rigidbody;
- };
-
- //! Enum representing movement directions during collision resolution.
- enum class Direction {
- //! No movement required.
- NONE,
- //! Movement in the X direction.
- X_DIRECTION,
- //! Movement in the Y direction.
- Y_DIRECTION,
- //! Movement in both X and Y directions.
- BOTH
- };
-
-public:
- /**
- * \brief Structure representing detailed collision information between two colliders.
- *
- * Includes information about the colliding objects and the resolution data for handling the collision.
- */
- struct CollisionInfo {
- Collider & this_collider;
- Transform & this_transform;
- Rigidbody & this_rigidbody;
- Metadata & this_metadata;
- Collider & other_collider;
- Transform & other_transform;
- Rigidbody & other_rigidbody;
- Metadata & other_metadata;
- //! The resolution vector for the collision.
+ ColliderInfo info;
vec2 resolution;
- //! The direction of movement for resolving the collision.
Direction resolution_direction = Direction::NONE;
};
+ //! Structure of a collider with additional components
+ template <typename ColliderType>
+ struct ColliderInternal {
+ ColliderType & collider;
+ Transform & transform;
+ Rigidbody & rigidbody;
+ };
+ //! Predefined BoxColliderInternal. (System is only made for this type)
+ using BoxColliderInternal = ColliderInternal<BoxCollider>;
+ //! Predefined CircleColliderInternal. (System is only made for this type)
+ using CircleColliderInternal = ColliderInternal<CircleCollider>;
+
public:
//! Updates the collision system by checking for collisions between colliders and handling them.
void fixed_update() override;
@@ -100,114 +117,90 @@ private:
CollisionInternalType get_collider_type(const collider_variant & collider1,
const collider_variant & collider2) const;
- /**
- * \brief Calculates the current position of a collider.
- *
- * Combines the Collider offset, Transform position, and Rigidbody offset to compute the position of the collider.
- *
- * \param collider_offset The offset of the collider.
- * \param transform The Transform of the associated game object.
- * \param rigidbody The Rigidbody of the associated game object.
- * \return The calculated position of the collider.
- */
- vec2 get_current_position(const vec2 & collider_offset, const Transform & transform,
- const Rigidbody & rigidbody) const;
-
private:
/**
- * \brief Handles collision resolution between two colliders.
+ * \brief Converts internal collision data into user-accessible collision information.
*
- * Processes collision data and adjusts objects to resolve collisions and/or calls the user oncollision script function.
+ * This function processes collision data from two colliding entities and packages it
+ * into a structured format that is accessible for further use,
+ * such as resolving collisions and triggering user-defined collision scripts.
*
* \param data1 Collision data for the first collider.
* \param data2 Collision data for the second collider.
*/
- void collision_handler_request(CollisionInternal & data1, CollisionInternal & data2);
+ CollisionInfo get_collision_info(const CollisionInternal & data1,
+ const CollisionInternal & data2) const;
/**
- * \brief Resolves collision between two colliders and calculates the movement required.
+ * \brief Corrects the collision resolution vector and determines its direction.
*
- * Determines the displacement and direction needed to separate colliders based on their types.
+ * This function adjusts the provided resolution vector based on the
+ * rigidbody's linear velocity to ensure consistent collision correction. If the resolution
+ * vector has only one non-zero component (either x or y), the missing component is computed
+ * based on the rigidbody's velocity. If both components are non-zero, it indicates a corner
+ * collision. The function also identifies the direction of the resolution and returns it.
*
- * \param data1 Collision data for the first collider.
- * \param data2 Collision data for the second collider.
- * \param type The type of collider pair.
- * \return A pair containing the resolution vector and direction for the first collider.
+ * \param resolution resolution vector that needs to be corrected
+ * \param rigidbody rigidbody data used to correct resolution
+ * \return A Direction indicating the resolution direction
*/
- std::pair<vec2, Direction> collision_handler(CollisionInternal & data1,
- CollisionInternal & data2,
- CollisionInternalType type);
+ Direction resolution_correction(vec2 & resolution, const Rigidbody::Data & rigidbody);
/**
- * \brief Calculates the resolution vector for two BoxColliders.
+ * \brief Determines the appropriate collision handler for a given collision event.
*
- * Computes the displacement required to separate two overlapping BoxColliders.
+ * This function identifies the correct collision resolution process based on the body types
+ * of the colliders involved in the collision. It delegates
+ * collision handling to specific handlers and calls collision event scripts
+ * as needed.
*
- * \param box_collider1 The first BoxCollider.
- * \param box_collider2 The second BoxCollider.
- * \param position1 The position of the first BoxCollider.
- * \param position2 The position of the second BoxCollider.
- * \return The resolution vector for the collision.
+ * \param info Collision information containing data about both colliders.
*/
- vec2 get_box_box_resolution(const BoxCollider & box_collider1,
- const BoxCollider & box_collider2, const vec2 & position1,
- const vec2 & position2) const;
+ void determine_collision_handler(const CollisionInfo & info);
/**
- * \brief Calculates the resolution vector for two CircleCollider.
+ * \brief Calls both collision script
*
- * Computes the displacement required to separate two overlapping CircleCollider.
+ * Calls both collision script to let user add additonal handling or handle full collision.
*
- * \param circle_collider1 The first CircleCollider.
- * \param circle_collider2 The second CircleCollider.
- * \param final_position1 The position of the first CircleCollider.
- * \param final_position2 The position of the second CircleCollider.
- * \return The resolution vector for the collision.
+ * \param info Collision information containing data about both colliders.
*/
- vec2 get_circle_circle_resolution(const CircleCollider & circle_collider1,
- const CircleCollider & circle_collider2,
- const vec2 & final_position1,
- const vec2 & final_position2) const;
+ void call_collision_events(const CollisionInfo & info);
/**
- * \brief Calculates the resolution vector for two CircleCollider.
- *
- * Computes the displacement required to separate two overlapping CircleCollider.
+ * \brief Handles collisions involving static objects.
*
- * \param circle_collider The first CircleCollider.
- * \param box_collider The second CircleCollider.
- * \param circle_position The position of the CircleCollider.
- * \param box_position The position of the BoxCollider.
- * \return The resolution vector for the collision.
- */
- vec2 get_circle_box_resolution(const CircleCollider & circle_collider,
- const BoxCollider & box_collider,
- const vec2 & circle_position,
- const vec2 & box_position) const;
-
- /**
- * \brief Determines the appropriate collision handler for a collision.
+ * This function resolves collisions between static and dynamic objects by adjusting
+ * the position of the static object and modifying the velocity of the dynamic object
+ * if elasticity is enabled. The position of the static object is corrected
+ * based on the collision resolution, and the dynamic object's velocity is adjusted
+ * accordingly to reflect the collision response.
*
- * Decides the correct resolution process based on the dynamic or static nature of the colliders involved.
+ * The handling includes stopping movement, applying bouncing based on the elasticity
+ * coefficient, and adjusting the position of the dynamic object if needed.
*
* \param info Collision information containing data about both colliders.
*/
- void determine_collision_handler(CollisionInfo & info);
+ void static_collision_handler(const CollisionInfo & info);
/**
- * \brief Handles collisions involving static objects.
+ * \brief Handles collisions involving dynamic objects.
*
- * Resolves collisions by adjusting positions and modifying velocities if bounce is enabled.
+ * Resolves collisions between two dynamic objects by adjusting their positions and modifying
+ * their velocities based on the collision resolution. If elasticity is enabled,
+ * the velocity of both objects is reversed and scaled by the respective elasticity coefficient.
+ * The positions of the objects are adjusted based on the collision resolution.
*
* \param info Collision information containing data about both colliders.
*/
- void static_collision_handler(CollisionInfo & info);
+ void dynamic_collision_handler(const CollisionInfo & info);
private:
/**
* \brief Checks for collisions between colliders.
*
- * Identifies collisions and generates pairs of colliding objects for further processing.
+ * This function checks all active colliders and identifies pairs of colliding objects.
+ * For each identified collision, the appropriate collision data is returned as pairs for further processing.
*
* \param colliders A collection of all active colliders.
* \return A list of collision pairs with their associated data.
@@ -216,86 +209,77 @@ private:
gather_collisions(std::vector<CollisionInternal> & colliders);
/**
- * \brief Checks if two collision layers have at least one common layer.
+ * \brief Checks if the settings allow collision
*
- * This function checks if there is any overlapping layer between the two inputs.
- * It compares each layer from the first input to see
- * if it exists in the second input. If at least one common layer is found,
- * the function returns true, indicating that the two colliders share a common
- * collision layer.
+ * This function checks if there is any collison layer where each object is located in.
+ * After checking the layers it checks the names and at last the tags.
+ * if in all three sets nothing is found collision can not happen.
*
- * \param layers1 all collision layers for the first collider.
- * \param layers2 all collision layers for the second collider.
- * \return Returns true if there is at least one common layer, false otherwise.
+ * \param this_rigidbody Rigidbody of first object
+ * \param other_rigidbody Rigidbody of second collider
+ * \param this_metadata Rigidbody of first object
+ * \param other_metadata Rigidbody of second object
+ * \return Returns true if there is at least one comparison found.
*/
-
- bool have_common_layer(const std::set<int> & layers1, const std::set<int> & layers2);
+ bool should_collide(const CollisionInternal & self,
+ const CollisionInternal & other) const; //done
/**
* \brief Checks for collision between two colliders.
*
- * Calls the appropriate collision detection function based on the collider types.
+ * This function determines whether two colliders are colliding based on their types.
+ * It calls the appropriate collision detection function based on the collider pair type and stores the collision resolution data.
+ * If a collision is detected, it returns true, otherwise false.
*
* \param first_info Collision data for the first collider.
* \param second_info Collision data for the second collider.
* \param type The type of collider pair.
* \return True if a collision is detected, otherwise false.
*/
- bool get_collision(const CollisionInternal & first_info,
- const CollisionInternal & second_info,
- CollisionInternalType type) const;
+ bool detect_collision(CollisionInternal & first_info, CollisionInternal & second_info,
+ const CollisionInternalType & type);
/**
* \brief Detects collisions between two BoxColliders.
*
- * \param box1 The first BoxCollider.
- * \param box2 The second BoxCollider.
- * \param transform1 Transform of the first object.
- * \param transform2 Transform of the second object.
- * \param rigidbody1 Rigidbody of the first object.
- * \param rigidbody2 Rigidbody of the second object.
- * \return True if a collision is detected, otherwise false.
+ * This function checks whether two `BoxCollider` are colliding based on their positions and scaled dimensions.
+ * If a collision is detected, it calculates the overlap along the X and Y axes and returns the resolution vector.
+ * If no collision is detected, it returns a vector with NaN values.
+
+ * \param box1 Information about the first BoxCollider.
+ * \param box2 Information about the second BoxCollider.
+ * \return If colliding, returns the resolution vector; otherwise, returns {NaN, NaN}.
*/
- bool get_box_box_collision(const BoxCollider & box1, const BoxCollider & box2,
- const Transform & transform1, const Transform & transform2,
- const Rigidbody & rigidbody1,
- const Rigidbody & rigidbody2) const;
+ vec2 get_box_box_detection(const BoxColliderInternal & box1,
+ const BoxColliderInternal & box2) const;
/**
* \brief Check collision for box on circle collider
*
- * \param box1 The BoxCollider
- * \param circle2 The CircleCollider
- * \param transform1 Transform of the first object.
- * \param transform2 Transform of the second object.
- * \param rigidbody1 Rigidbody of the first object.
- * \param rigidbody2 Rigidbody of the second object.
- * \return True if a collision is detected, otherwise false.
+ * This function detects if a collision occurs between a rectangular box and a circular collider.
+ * If a collision is detected, the function calculates the resolution vector to resolve the collision.
+ * If no collision is detected, it returns a vector with NaN values
+ *
+ * \param box1 Information about the BoxCollider.
+ * \param circle2 Information about the circleCollider.
+ * \return If colliding, returns the resolution vector; otherwise, returns {NaN, NaN}.
*/
- bool get_box_circle_collision(const BoxCollider & box1, const CircleCollider & circle2,
- const Transform & transform1, const Transform & transform2,
- const Rigidbody & rigidbody1,
- const Rigidbody & rigidbody2) const;
+ vec2 get_box_circle_detection(const BoxColliderInternal & box1,
+ const CircleColliderInternal & circle2) const;
/**
* \brief Check collision for circle on circle collider
*
- * \param circle1 First CircleCollider
- * \param circle2 Second CircleCollider
- * \param transform1 Transform of the first object.
- * \param transform2 Transform of the second object.
- * \param rigidbody1 Rigidbody of the first object.
- * \param rigidbody2 Rigidbody of the second object.
- * \return True if a collision is detected, otherwise false.
+ * This function detects if a collision occurs between two circular colliders.
+ * If a collision is detected, it calculates the resolution vector to resolve the collision.
+ * If no collision is detected, it returns a vector with NaN values.
*
- * \return status of collision
+ * \param circle1 Information about the first circleCollider.
+ * \param circle2 Information about the second circleCollider.
+ * \return If colliding, returns the resolution vector; otherwise, returns {NaN, NaN}.
*/
- bool get_circle_circle_collision(const CircleCollider & circle1,
- const CircleCollider & circle2,
- const Transform & transform1,
- const Transform & transform2,
- const Rigidbody & rigidbody1,
- const Rigidbody & rigidbody2) const;
+ vec2 get_circle_circle_detection(const CircleColliderInternal & circle1,
+ const CircleColliderInternal & circle2) const;
};
/**
diff --git a/src/crepe/system/ParticleSystem.cpp b/src/crepe/system/ParticleSystem.cpp
index bbc7366..5e575e4 100644
--- a/src/crepe/system/ParticleSystem.cpp
+++ b/src/crepe/system/ParticleSystem.cpp
@@ -7,6 +7,7 @@
#include "../api/Transform.h"
#include "../manager/ComponentManager.h"
#include "../manager/LoopTimerManager.h"
+#include "util/AbsolutePosition.h"
#include "ParticleSystem.h"
@@ -48,9 +49,10 @@ void ParticleSystem::fixed_update() {
void ParticleSystem::emit_particle(ParticleEmitter & emitter, const Transform & transform) {
constexpr float DEG_TO_RAD = M_PI / 180.0;
- vec2 initial_position = emitter.data.offset + transform.position;
+ vec2 initial_position = AbsolutePosition::get_position(transform, emitter.data.offset);
float random_angle
- = this->generate_random_angle(emitter.data.min_angle, emitter.data.max_angle);
+ = this->generate_random_angle(emitter.data.min_angle + transform.rotation,
+ emitter.data.max_angle + transform.rotation);
float random_speed
= this->generate_random_speed(emitter.data.min_speed, emitter.data.max_speed);
diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp
index 33218f6..698301e 100644
--- a/src/crepe/system/RenderSystem.cpp
+++ b/src/crepe/system/RenderSystem.cpp
@@ -16,6 +16,9 @@
#include "../facade/Texture.h"
#include "../manager/ComponentManager.h"
#include "../manager/ResourceManager.h"
+#include "api/Text.h"
+#include "facade/Font.h"
+#include "util/AbsolutePosition.h"
#include "RenderSystem.h"
#include "types.h"
@@ -70,11 +73,34 @@ RefVector<Sprite> RenderSystem::sort(RefVector<Sprite> & objs) const {
void RenderSystem::frame_update() {
this->clear_screen();
this->render();
+ this->render_text();
this->present_screen();
}
-bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) {
+void RenderSystem::render_text() {
+ SDLContext & ctx = this->mediator.sdl_context;
+ ComponentManager & mgr = this->mediator.component_manager;
+ ResourceManager & resource_manager = this->mediator.resource_manager;
+
+ RefVector<Text> texts = mgr.get_components_by_type<Text>();
+
+ for (Text & text : texts) {
+ if (!text.active) continue;
+ if (!text.font.has_value())
+ text.font.emplace(ctx.get_font_from_name(text.font_family));
+
+ const Font & font = resource_manager.get<Font>(text.font.value());
+ const auto & transform
+ = mgr.get_components_by_id<Transform>(text.game_object_id).front().get();
+ ctx.draw_text(SDLContext::RenderText{
+ .text = text,
+ .font = font,
+ .transform = transform,
+ });
+ }
+}
+bool RenderSystem::render_particle(const Sprite & sprite, const Transform & transform) {
ComponentManager & mgr = this->mediator.component_manager;
SDLContext & ctx = this->mediator.sdl_context;
ResourceManager & resource_manager = this->mediator.resource_manager;
@@ -92,29 +118,30 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale)
for (const Particle & p : em.particles) {
if (!p.active) continue;
+ if (p.time_in_life < em.data.begin_lifespan) continue;
ctx.draw(SDLContext::RenderContext{
.sprite = sprite,
.texture = res,
.pos = p.position,
- .angle = p.angle,
- .scale = scale,
+ .angle = p.angle + transform.rotation,
+ .scale = transform.scale,
});
}
}
return rendering_particles;
}
-void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) {
+void RenderSystem::render_normal(const Sprite & sprite, const Transform & transform) {
SDLContext & ctx = this->mediator.sdl_context;
ResourceManager & resource_manager = this->mediator.resource_manager;
const Texture & res = resource_manager.get<Texture>(sprite.source);
-
+ vec2 pos = AbsolutePosition::get_position(transform, sprite.data.position_offset);
ctx.draw(SDLContext::RenderContext{
.sprite = sprite,
.texture = res,
- .pos = tm.position,
- .angle = tm.rotation,
- .scale = tm.scale,
+ .pos = pos,
+ .angle = transform.rotation,
+ .scale = transform.scale,
});
}
@@ -126,35 +153,16 @@ void RenderSystem::render() {
ResourceManager & resource_manager = this->mediator.resource_manager;
RefVector<Sprite> sorted_sprites = this->sort(sprites);
RefVector<Text> text_components = mgr.get_components_by_type<Text>();
- for (Text & text : text_components) {
- const Transform & transform
- = mgr.get_components_by_id<Transform>(text.game_object_id).front().get();
- this->render_text(text, transform);
- }
+
for (const Sprite & sprite : sorted_sprites) {
if (!sprite.active) continue;
const Transform & transform
= mgr.get_components_by_id<Transform>(sprite.game_object_id).front().get();
- bool rendered_particles = this->render_particle(sprite, transform.scale);
+ bool rendered_particles = this->render_particle(sprite, transform);
if (rendered_particles) continue;
this->render_normal(sprite, transform);
}
}
-void RenderSystem::render_text(Text & text, const Transform & tm) {
- SDLContext & ctx = this->mediator.sdl_context;
-
- if (!text.font.has_value()) {
- text.font.emplace(ctx.get_font_from_name(text.font_family));
- }
-
- ResourceManager & resource_manager = this->mediator.resource_manager;
-
- if (!text.font.has_value()) {
- return;
- }
- const Asset & font_asset = text.font.value();
- const Font & res = resource_manager.get<Font>(font_asset);
-}
diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h
index 656ad5b..627a743 100644
--- a/src/crepe/system/RenderSystem.h
+++ b/src/crepe/system/RenderSystem.h
@@ -36,34 +36,28 @@ private:
//! Updates the active camera used for rendering.
void update_camera();
- //! Renders the whole screen
+ //! Renders all the sprites and particles
void render();
+ //! Renders all Text components
+ void render_text();
+
+private:
/**
* \brief Renders all the particles on the screen from a given sprite.
*
* \param sprite renders the particles with given texture
- * \param tm the Transform component for scale. This is not a const reference because each
- * particle has a position and rotation that needs to overwrite the transform position and
- * rotation without overwriting the current transform. and because the transform
- * constructor is now protected i cannot make tmp inside
+ * \param transform the component that holds the position, rotation, and scale.
* \return true if particles have been rendered
*/
- bool render_particle(const Sprite & sprite, const double & scale);
- /**
- * \brief Renders all Text components
- *
- * \param text The text component to be rendered.
- * \param tm the Transform component that holds the position,rotation and scale
- */
- void render_text(Text & text, const Transform & tm);
+ bool render_particle(const Sprite & sprite, const Transform & transform);
/**
* \brief renders a sprite with a Transform component on the screen
*
* \param sprite the sprite component that holds all the data
- * \param tm the Transform component that holds the position,rotation and scale
+ * \param transform the Transform component that holds the position,rotation and scale
*/
- void render_normal(const Sprite & sprite, const Transform & tm);
+ void render_normal(const Sprite & sprite, const Transform & transform);
/**
* \brief sort a vector sprite objects with
@@ -72,12 +66,6 @@ private:
* \return returns a sorted reference vector
*/
RefVector<Sprite> sort(RefVector<Sprite> & objs) const;
-
- /**
- * \todo Add text rendering using SDL_ttf for text components.
- * \todo Implement a text component and a button component.
- * \todo Consider adding text input functionality.
- */
};
} // namespace crepe
diff --git a/src/crepe/util/AbsolutePosition.cpp b/src/crepe/util/AbsolutePosition.cpp
new file mode 100644
index 0000000..29ade23
--- /dev/null
+++ b/src/crepe/util/AbsolutePosition.cpp
@@ -0,0 +1,20 @@
+#include "AbsolutePosition.h"
+
+using namespace crepe;
+
+vec2 AbsolutePosition::get_position(const Transform & transform, const vec2 & offset) {
+ // Get the rotation in radians
+ float radians1 = transform.rotation * (M_PI / 180.0);
+
+ // Calculate total offset with scale
+ vec2 total_offset = offset * transform.scale;
+
+ // Rotate
+ float rotated_total_offset_x1
+ = total_offset.x * cos(radians1) - total_offset.y * sin(radians1);
+ float rotated_total_offset_y1
+ = total_offset.x * sin(radians1) + total_offset.y * cos(radians1);
+
+ // Final positions considering scaling and rotation
+ return (transform.position + vec2(rotated_total_offset_x1, rotated_total_offset_y1));
+}
diff --git a/src/crepe/util/AbsolutePosition.h b/src/crepe/util/AbsolutePosition.h
new file mode 100644
index 0000000..857c1ac
--- /dev/null
+++ b/src/crepe/util/AbsolutePosition.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "api/Transform.h"
+
+#include "types.h"
+
+namespace crepe {
+
+/**
+ * \brief A class for calculating the absolute position of an object.
+ *
+ * This class provides a utility function to get the position of an object in the world space,
+ * taking into account the transform and any additional offset.
+ */
+class AbsolutePosition {
+public:
+ /**
+ * \brief Get the absolute position of an object.
+ *
+ * This function calculates the absolute position by combining the transform position with an optional offset.
+ *
+ * \param transform The transform of the object, which contains its position, rotation, and scale.
+ * \param offset The offset to apply to the object's position (in local space).
+ * \return The absolute position of the object as a 2D vector.
+ */
+ static vec2 get_position(const Transform & transform, const vec2 & offset);
+};
+
+} // namespace crepe
diff --git a/src/crepe/util/CMakeLists.txt b/src/crepe/util/CMakeLists.txt
index 94ed906..33160a7 100644
--- a/src/crepe/util/CMakeLists.txt
+++ b/src/crepe/util/CMakeLists.txt
@@ -1,6 +1,7 @@
target_sources(crepe PUBLIC
LogColor.cpp
Log.cpp
+ AbsolutePosition.cpp
)
target_sources(crepe PUBLIC FILE_SET HEADERS FILES
@@ -11,5 +12,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES
Proxy.hpp
OptionalRef.h
OptionalRef.hpp
+ AbsolutePosition.h
)
diff --git a/src/example/game.cpp b/src/example/game.cpp
index 3975650..7ee784a 100644
--- a/src/example/game.cpp
+++ b/src/example/game.cpp
@@ -1,9 +1,12 @@
+#include "api/Asset.h"
+#include "api/BehaviorScript.h"
#include "api/CircleCollider.h"
#include "api/ParticleEmitter.h"
#include "api/Scene.h"
#include "manager/ComponentManager.h"
#include "manager/Mediator.h"
#include "types.h"
+#include <cmath>
#include <crepe/api/BoxCollider.h>
#include <crepe/api/Camera.h>
#include <crepe/api/Color.h>
@@ -17,267 +20,293 @@
#include <crepe/api/Vector2.h>
using namespace crepe;
-
using namespace std;
-class MyScript1 : public Script {
- bool flip = false;
+class ScriptBox : public Script {
+public:
bool oncollision(const CollisionEvent & test) {
- Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id);
+ Log::logf("Box {} on_collision() with {}", test.info.self.metadata.game_object_id, test.info.other.metadata.game_object_id);
return true;
}
- bool keypressed(const KeyPressEvent & test) {
- Log::logf("Box script keypressed()");
- switch (test.key) {
- case Keycode::A: {
- Rigidbody & tf = this->get_component<Rigidbody>();
- tf.data.linear_velocity.x -= 1;
- break;
- }
- case Keycode::W: {
- Rigidbody & tf = this->get_component<Rigidbody>();
- // tf.data.linear_velocity.y -= 1;
- tf.add_force_linear({0, -1});
- break;
- }
- case Keycode::S: {
- Rigidbody & tf = this->get_component<Rigidbody>();
- tf.data.linear_velocity.y += 1;
- break;
- }
- case Keycode::D: {
- Rigidbody & tf = this->get_component<Rigidbody>();
- tf.data.linear_velocity.x += 1;
- break;
- }
- case Keycode::E: {
- if (flip) {
- flip = false;
- this->get_component<BoxCollider>().active = true;
- this->get_components<Sprite>()[0].get().active = true;
- this->get_component<CircleCollider>().active = false;
- this->get_components<Sprite>()[1].get().active = false;
- } else {
- flip = true;
- this->get_component<BoxCollider>().active = false;
- this->get_components<Sprite>()[0].get().active = false;
- this->get_component<CircleCollider>().active = true;
- this->get_components<Sprite>()[1].get().active = true;
- }
-
- //add collider switch
- break;
- }
- case Keycode::Q: {
- Rigidbody & rg = this->get_component<Rigidbody>();
- rg.data.angular_velocity = 1;
- break;
- }
- default:
- break;
- }
- return false;
- }
void init() {
- Log::logf("init");
subscribe<CollisionEvent>(
[this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); });
- subscribe<KeyPressEvent>(
- [this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); });
- }
- void update(duration_t) {
- Rigidbody & tf = this->get_component<Rigidbody>();
- Log::logf("linear_velocity.x {}", tf.data.linear_velocity.x);
- Log::logf("linear_velocity.y {}", tf.data.linear_velocity.y);
- // tf.data.linear_velocity = {0,0};
}
};
-class MyScript2 : public Script {
- bool flip = false;
+class ScriptCircle : public Script {
+public:
bool oncollision(const CollisionEvent & test) {
- Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id);
+ Log::logf("Circle {} on_collision() with {}", test.info.self.metadata.game_object_id, test.info.other.metadata.game_object_id);
return true;
}
- bool keypressed(const KeyPressEvent & test) {
- Log::logf("Box script keypressed()");
- switch (test.key) {
- case Keycode::LEFT: {
- Transform & tf = this->get_component<Transform>();
- tf.position.x -= 1;
- break;
- }
- case Keycode::UP: {
- Transform & tf = this->get_component<Transform>();
- tf.position.y -= 1;
- break;
- }
- case Keycode::DOWN: {
- Transform & tf = this->get_component<Transform>();
- tf.position.y += 1;
- break;
- }
- case Keycode::RIGHT: {
- Transform & tf = this->get_component<Transform>();
- tf.position.x += 1;
- break;
- }
- case Keycode::PAUSE: {
- if (flip) {
- flip = false;
- this->get_component<BoxCollider>().active = true;
- this->get_components<Sprite>()[0].get().active = true;
- this->get_component<CircleCollider>().active = false;
- this->get_components<Sprite>()[1].get().active = false;
- } else {
- flip = true;
- this->get_component<BoxCollider>().active = false;
- this->get_components<Sprite>()[0].get().active = false;
- this->get_component<CircleCollider>().active = true;
- this->get_components<Sprite>()[1].get().active = true;
- }
-
- //add collider switch
- break;
- }
- default:
- break;
- }
- return false;
- }
void init() {
- Log::logf("init");
subscribe<CollisionEvent>(
[this](const CollisionEvent & ev) -> bool { return this->oncollision(ev); });
- subscribe<KeyPressEvent>(
- [this](const KeyPressEvent & ev) -> bool { return this->keypressed(ev); });
}
+};
+
+class ScriptMoveToLeft : public Script {
+public:
void update() {
- // Retrieve component from the same GameObject this script is on
+ Transform & transform = this->get_component<Transform>();
+ transform.position.x -= 0.02;
}
};
-class ConcreteScene1 : public Scene {
+class ScriptMoveToRight : public Script {
public:
- using Scene::Scene;
+ void update() {
+ Transform & transform = this->get_component<Transform>();
+ transform.position.x += 0.02;
+ }
+};
+class ConcreteScene1 : public Scene {
+public:
void load_scene() {
+ GameObject camera = this->new_object("camera");
+ camera.add_component<Camera>(ivec2(1080, 720), vec2(10, 10), Camera::Data{
+ .bg_color = Color::WHITE,
+ .zoom = 1
+ });
- Color color(0, 0, 0, 255);
+ GameObject reference = this->new_object("reference", "tag", vec2(0, 0), 0, 1);
+ Asset reference_asset = Asset("asset/texture/square.png");
+ reference.add_component<Sprite>(reference_asset, Sprite::Data{
+ .color = Color::RED,
+ .sorting_in_layer = 10,
+ .order_in_layer = 0,
+ .size = vec2(0.1, 0.1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(0, 0),
+ });
- float screen_size_width = 320;
- float screen_size_height = 240;
- float world_collider = 1000;
- //define playable world
- GameObject world = new_object(
- "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1);
- world.add_component<Rigidbody>(Rigidbody::Data{
- .mass = 0,
- .gravity_scale = 0,
- .body_type = Rigidbody::BodyType::STATIC,
- .offset = {0, 0},
+ /*GameObject box_1 = this->new_object("box_1", "tag", vec2(0, 0), 0, 1);
+ Asset box_1_asset = Asset("asset/texture/square.png");
+ box_1.add_component<Sprite>(box_1_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(0, 0.5),
});
- world.add_component<BoxCollider>(
- vec2{world_collider, world_collider},
- vec2{0, 0 - (screen_size_height / 2 + world_collider / 2)}); // Top
- world.add_component<BoxCollider>(
- vec2{world_collider, world_collider},
- vec2{0, screen_size_height / 2 + world_collider / 2}); // Bottom
- world.add_component<BoxCollider>(
- vec2{world_collider, world_collider},
- vec2{0 - (screen_size_width / 2 + world_collider / 2), 0}); // Left
- world.add_component<BoxCollider>(
- vec2{world_collider, world_collider},
- vec2{screen_size_width / 2 + world_collider / 2, 0}); // right
- world.add_component<Camera>(
- ivec2{static_cast<int>(screen_size_width), static_cast<int>(screen_size_height)},
- vec2{screen_size_width, screen_size_height},
- Camera::Data{
- .bg_color = Color::WHITE,
- .zoom = 1,
- });
+ Asset box_1_asset2 = Asset("asset/texture/test_ap43.png");
+ box_1.add_component<Sprite>(box_1_asset2, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(0, -0.5),
+ });*/
+
+ /*GameObject particles = this->new_object("particles", "tag", vec2(-1, 0), 180, 1);
+ Asset particles_asset = Asset("asset/texture/test_ap43.png");
+ Sprite & particles_sprite = particles.add_component<Sprite>(particles_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(0, 0),
+ });
+ ParticleEmitter & particles_emitter = particles.add_component<ParticleEmitter>(particles_sprite, ParticleEmitter::Data{
+ .offset = vec2(0, 0),
+ .emission_rate = 1,
+ .min_speed = 1,
+ .max_speed = 1,
+ .min_angle = 0,
+ .max_angle = 0,
+ .end_lifespan = 4,
+ });*/
+
+ const bool SCRIPT = false;
- GameObject game_object1 = new_object(
- "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1);
- game_object1.add_component<Rigidbody>(Rigidbody::Data{
- .mass = 1,
- .gravity_scale = 1,
- .body_type = Rigidbody::BodyType::DYNAMIC,
- .linear_velocity = {0, 1},
- .constraints = {0, 0, 0},
- .elastisity_coefficient = 0,
- .offset = {0, 0},
+ const Rigidbody::BodyType BODYTYPE_LEFT = Rigidbody::BodyType::DYNAMIC;
+ const Rigidbody::BodyType BODYTYPE_RIGHT = Rigidbody::BodyType::DYNAMIC;
+ const bool BOUNCE_LEFT = false;
+ const bool BOUNCE_RIGHT = false;
+ const bool KINEMATIC_COLLISION = true;
+ const bool ONTOP = false;
+
+ const float SCALE = 0.5;
+ const float OFFSET_X_LEFT = 0;
+ const float OFFSET_X_RIGHT = 0;
+ const float OFFSET_Y_LEFT = 0;
+ const float OFFSET_Y_RIGHT = 0;
+
+ GameObject box_1 = this->new_object("box_1", "tag", ONTOP ? vec2(-0.25, -4) : vec2(-2, -4), 0, SCALE);
+ Asset box_1_asset = Asset("asset/texture/square.png");
+ box_1.add_component<Sprite>(box_1_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT),
+ });
+ box_1.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_LEFT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{1, 0},
+ .elasticity_coefficient = BOUNCE_LEFT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
});
- // add box with boxcollider
- game_object1.add_component<BoxCollider>(vec2{20, 20});
- game_object1.add_component<BehaviorScript>().set_script<MyScript1>();
+ box_1.add_component<BehaviorScript>().set_script<ScriptMoveToRight>().active = SCRIPT;
+ box_1.add_component<BoxCollider>(vec2(1, 1), vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT));
+ box_1.add_component<BehaviorScript>().set_script<ScriptBox>();
- Asset img1{"asset/texture/square.png"};
- game_object1.add_component<Sprite>(img1, Sprite::Data{
- .size = {20, 20},
- });
+ GameObject circle_1 = this->new_object("ricle_1", "tag", ONTOP ? vec2(0.25, -4) : vec2(2, -4), 0, SCALE);
+ Asset circle_1_asset = Asset("asset/texture/circle.png");
+ circle_1.add_component<Sprite>(circle_1_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT),
+ });
+ circle_1.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_RIGHT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{-1, 0},
+ .elasticity_coefficient = BOUNCE_RIGHT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
+ });
+ circle_1.add_component<BehaviorScript>().set_script<ScriptMoveToLeft>().active = SCRIPT;
+ circle_1.add_component<CircleCollider>(0.5, vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT));
+ circle_1.add_component<BehaviorScript>().set_script<ScriptCircle>();
- //add circle with cirlcecollider deactiveated
- game_object1.add_component<CircleCollider>(10).active = false;
- Asset img2{"asset/texture/circle.png"};
- game_object1
- .add_component<Sprite>(img2,
- Sprite::Data{
- .size = {20, 20},
- })
- .active
- = false;
+ GameObject circle_2 = this->new_object("ricle_2", "tag", ONTOP ? vec2(-0.25, -1.5) : vec2(-2.5, -1.5), 0, SCALE);
+ Asset circle_2_asset = Asset("asset/texture/circle.png");
+ circle_2.add_component<Sprite>(circle_2_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT),
+ });
+ circle_2.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_LEFT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{1, 0},
+ .elasticity_coefficient = BOUNCE_LEFT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
+ });
+ circle_2.add_component<BehaviorScript>().set_script<ScriptMoveToRight>().active = SCRIPT;
+ circle_2.add_component<CircleCollider>(0.5, vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT));
+ circle_2.add_component<BehaviorScript>().set_script<ScriptCircle>();
- GameObject game_object2 = new_object(
- "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1);
- game_object2.add_component<Rigidbody>(Rigidbody::Data{
- .mass = 1,
+ GameObject box_2 = this->new_object("box_2", "tag", ONTOP ? vec2(0.25, -1.5) : vec2(2.5, -1.5), 0, SCALE);
+ Asset box_2_asset = Asset("asset/texture/square.png");
+ box_2.add_component<Sprite>(box_2_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT),
+ });
+ box_2.add_component<Rigidbody>(Rigidbody::Data{
.gravity_scale = 0,
- .body_type = Rigidbody::BodyType::STATIC,
- .linear_velocity = {0, 0},
- .constraints = {0, 0, 0},
- .elastisity_coefficient = 1,
- .offset = {0, 0},
+ .body_type = BODYTYPE_RIGHT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{-1, 0},
+ .elasticity_coefficient = BOUNCE_RIGHT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
});
- // add box with boxcollider
- game_object2.add_component<BoxCollider>(vec2{20, 20});
- game_object2.add_component<BehaviorScript>().set_script<MyScript2>();
+ box_2.add_component<BehaviorScript>().set_script<ScriptMoveToLeft>().active = SCRIPT;
+ box_2.add_component<BoxCollider>(vec2(1, 1), vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT));
+ box_2.add_component<BehaviorScript>().set_script<ScriptBox>();
- game_object2.add_component<Sprite>(img1, Sprite::Data{
- .size = {20, 20},
- });
+ GameObject box_3 = this->new_object("box_3", "tag", ONTOP ? vec2(-0.25, 1.5) : vec2(-3, 1.5), 0, SCALE);
+ Asset box_3_asset = Asset("asset/texture/square.png");
+ box_3.add_component<Sprite>(box_3_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT),
+ });
+ box_3.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_LEFT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{1, 0},
+ .elasticity_coefficient = BOUNCE_LEFT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
+ });
+ box_3.add_component<BehaviorScript>().set_script<ScriptMoveToRight>().active = SCRIPT;
+ box_3.add_component<BoxCollider>(vec2(1, 1), vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT));
+ box_3.add_component<BehaviorScript>().set_script<ScriptBox>();
- //add circle with cirlcecollider deactiveated
- game_object2.add_component<CircleCollider>(10).active = false;
+ GameObject box_4 = this->new_object("box_4", "tag", ONTOP ? vec2(0.25, 1.5) : vec2(3, 1.5), 0, SCALE);
+ Asset box_4_asset = Asset("asset/texture/square.png");
+ box_4.add_component<Sprite>(box_4_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT),
+ });
+ box_4.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_RIGHT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{-1, 0},
+ .elasticity_coefficient = BOUNCE_RIGHT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
+ });
+ box_4.add_component<BehaviorScript>().set_script<ScriptMoveToLeft>().active = SCRIPT;
+ box_4.add_component<BoxCollider>(vec2(1, 1), vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT));
+ box_4.add_component<BehaviorScript>().set_script<ScriptBox>();
- game_object2
- .add_component<Sprite>(img2,
- Sprite::Data{
- .size = {20, 20},
- })
- .active
- = false;
- Asset img5{"asset/texture/square.png"};
+ GameObject circle_3 = this->new_object("ricle_3", "tag", ONTOP ? vec2(-0.25, 4) : vec2(-3.5, 4), 0, SCALE);
+ Asset circle_3_asset = Asset("asset/texture/circle.png");
+ circle_3.add_component<Sprite>(circle_3_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT),
+ });
+ circle_3.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_LEFT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{1, 0},
+ .elasticity_coefficient = BOUNCE_LEFT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
+ });
+ circle_3.add_component<BehaviorScript>().set_script<ScriptMoveToRight>().active = SCRIPT;
+ circle_3.add_component<CircleCollider>(0.5, vec2(OFFSET_X_LEFT, OFFSET_Y_LEFT));
+ circle_3.add_component<BehaviorScript>().set_script<ScriptCircle>();
- GameObject particle = new_object(
- "Name", "Tag", vec2{screen_size_width / 2, screen_size_height / 2}, 0, 1);
- auto & particle_image = particle.add_component<Sprite>(img5, Sprite::Data{
- .size = {5, 5},
- });
- auto & test
- = particle.add_component<ParticleEmitter>(particle_image, ParticleEmitter::Data{
- .offset = {0, 0},
- .max_particles = 256,
- .emission_rate = 1,
- .min_speed = 10,
- .max_speed = 20,
- .min_angle = -20,
- .max_angle = 20,
- .begin_lifespan = 0,
- .end_lifespan = 5,
- });
+ GameObject circle_4 = this->new_object("ricle_4", "tag", ONTOP ? vec2(0.25, 4) : vec2(3.5, 4), 0, SCALE);
+ Asset circle_4_asset = Asset("asset/texture/circle.png");
+ circle_4.add_component<Sprite>(circle_4_asset, Sprite::Data{
+ .sorting_in_layer = 0,
+ .order_in_layer = 0,
+ .size = vec2(1, 1),
+ .angle_offset = 0,
+ .scale_offset = 1,
+ .position_offset = vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT),
+ });
+ circle_4.add_component<Rigidbody>(Rigidbody::Data{
+ .gravity_scale = 0,
+ .body_type = BODYTYPE_RIGHT,
+ .linear_velocity = SCRIPT ? vec2{0, 0} : vec2{-1, 0},
+ .elasticity_coefficient = BOUNCE_RIGHT ? 0.5 : 0,
+ .kinematic_collision = KINEMATIC_COLLISION,
+ });
+ circle_4.add_component<BehaviorScript>().set_script<ScriptMoveToLeft>().active = SCRIPT;
+ circle_4.add_component<CircleCollider>(0.5, vec2(OFFSET_X_RIGHT, OFFSET_Y_RIGHT));
+ circle_4.add_component<BehaviorScript>().set_script<ScriptCircle>();
}
string get_name() const { return "scene1"; }
diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp
index add43f4..5440fdd 100644
--- a/src/example/rendering_particle.cpp
+++ b/src/example/rendering_particle.cpp
@@ -1,4 +1,7 @@
+
+
#include "api/Asset.h"
+#include "api/Text.h"
#include <crepe/Component.h>
#include <crepe/api/Animator.h>
#include <crepe/api/Button.h>
@@ -13,7 +16,6 @@
#include <crepe/manager/ComponentManager.h>
#include <crepe/manager/Mediator.h>
#include <crepe/types.h>
-#include <iostream>
using namespace crepe;
using namespace std;
@@ -21,15 +23,11 @@ using namespace std;
class TestScene : public Scene {
public:
void load_scene() {
-
- cout << "TestScene" << endl;
- Mediator & mediator = this->mediator;
- ComponentManager & mgr = mediator.component_manager;
- GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 1);
+ GameObject game_object = new_object("", "", vec2{0, 0}, 0, 1);
Color color(255, 255, 255, 255);
- Asset img{"asset/spritesheet/spritesheet_test.png"};
+ Asset img{"asset/texture/square.png"};
Sprite & test_sprite = game_object.add_component<Sprite>(
img, Sprite::Data{
@@ -37,29 +35,34 @@ public:
.flip = Sprite::FlipSettings{false, false},
.sorting_in_layer = 2,
.order_in_layer = 2,
- .size = {0, 100},
+ .size = {1, 1},
.angle_offset = 0,
- .position_offset = {0, 0},
+ .position_offset = {0, 1},
+ .world_space = false,
});
+ //auto & emitter = game_object.add_component<ParticleEmitter>(test_sprite, ParticleEmitter::Data{});
- //auto & anim = game_object.add_component<Animator>(test_sprite,ivec2{32, 64}, uvec2{4,1}, Animator::Data{});
- //anim.set_anim(0);
+ Sprite & test_sprite1
+ = game_object.add_component<Sprite>(img, Sprite::Data{
+ .color = color,
+ .size = {1, 1},
+ .position_offset = {0, -1},
+ .world_space = false,
+ });
- auto & cam = game_object.add_component<Camera>(ivec2{720, 1280}, vec2{400, 400},
+ auto & cam = game_object.add_component<Camera>(ivec2{1280, 720}, vec2{5, 5},
Camera::Data{
.bg_color = Color::WHITE,
+ .postion_offset = {1000, 1000},
});
- function<void()> on_click = [&]() { cout << "button clicked" << std::endl; };
- function<void()> on_enter = [&]() { cout << "enter" << std::endl; };
- function<void()> on_exit = [&]() { cout << "exit" << std::endl; };
+ /*
+ game_object.add_component<Text>(vec2{1, 1}, vec2{0, -0.5}, "ComicSansMS",
+ Text::Data{.text_color = Color::RED}, "test TEST");
- auto & button
- = game_object.add_component<Button>(vec2{200, 200}, vec2{0, 0}, on_click, false);
- button.on_mouse_enter = on_enter;
- button.on_mouse_exit = on_exit;
- button.is_toggle = true;
- button.active = true;
+ game_object.add_component<Text>(vec2{1, 1}, vec2{0, 0.5}, "ComicSansMS",
+ Text::Data{.text_color = Color::BLACK}, "TEST test");
+ */
}
string get_name() const { return "TestScene"; };
diff --git a/src/test/CollisionTest.cpp b/src/test/CollisionTest.cpp
index 73a964a..c8d804c 100644
--- a/src/test/CollisionTest.cpp
+++ b/src/test/CollisionTest.cpp
@@ -67,7 +67,6 @@ public:
world.add_component<Rigidbody>(Rigidbody::Data{
// TODO: remove unrelated properties:
.body_type = Rigidbody::BodyType::STATIC,
- .offset = {0, 0},
});
// Create a box with an inner size of 10x10 units
world.add_component<BoxCollider>(vec2{100, 100}, vec2{0, -100}); // Top
@@ -81,8 +80,7 @@ public:
.body_type = Rigidbody::BodyType::DYNAMIC,
.linear_velocity = {0, 0},
.constraints = {0, 0, 0},
- .elastisity_coefficient = 1,
- .offset = {0, 0},
+ .elasticity_coefficient = 1,
.collision_layers = {0},
});
game_object1.add_component<BoxCollider>(vec2{10, 10}, vec2{0, 0});
@@ -97,8 +95,7 @@ public:
.body_type = Rigidbody::BodyType::DYNAMIC,
.linear_velocity = {0, 0},
.constraints = {0, 0, 0},
- .elastisity_coefficient = 1,
- .offset = {0, 0},
+ .elasticity_coefficient = 1,
.collision_layers = {0},
});
game_object2.add_component<BoxCollider>(vec2{10, 10}, vec2{0, 0});
@@ -116,11 +113,11 @@ TEST_F(CollisionTest, collision_example) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
};
EXPECT_FALSE(collision_happend);
collision_sys.fixed_update();
@@ -131,16 +128,16 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both_no_velocity) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, 10);
EXPECT_EQ(ev.info.resolution.y, 10);
EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH);
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
- EXPECT_EQ(ev.info.resolution.x, 10);
- EXPECT_EQ(ev.info.resolution.y, 10);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
+ EXPECT_EQ(ev.info.resolution.x, -10);
+ EXPECT_EQ(ev.info.resolution.y, -10);
EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH);
};
EXPECT_FALSE(collision_happend);
@@ -154,7 +151,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction_no_velocity) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, -5);
EXPECT_EQ(ev.info.resolution.y, 0);
EXPECT_EQ(ev.info.resolution_direction,
@@ -162,7 +159,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction_no_velocity) {
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
EXPECT_EQ(ev.info.resolution.x, 5);
EXPECT_EQ(ev.info.resolution.y, 0);
EXPECT_EQ(ev.info.resolution_direction,
@@ -179,7 +176,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction_no_velocity) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, 0);
EXPECT_EQ(ev.info.resolution.y, -5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -187,7 +184,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction_no_velocity) {
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
EXPECT_EQ(ev.info.resolution.x, 0);
EXPECT_EQ(ev.info.resolution.y, 5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -204,16 +201,16 @@ TEST_F(CollisionTest, collision_box_box_dynamic_both) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, 10);
EXPECT_EQ(ev.info.resolution.y, 10);
EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH);
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
- EXPECT_EQ(ev.info.resolution.x, 10);
- EXPECT_EQ(ev.info.resolution.y, 10);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
+ EXPECT_EQ(ev.info.resolution.x, -10);
+ EXPECT_EQ(ev.info.resolution.y, -10);
EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH);
};
EXPECT_FALSE(collision_happend);
@@ -231,7 +228,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, -5);
EXPECT_EQ(ev.info.resolution.y, 5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -239,7 +236,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_x_direction) {
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
EXPECT_EQ(ev.info.resolution.x, 5);
EXPECT_EQ(ev.info.resolution.y, -5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -260,7 +257,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, 5);
EXPECT_EQ(ev.info.resolution.y, -5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -268,7 +265,7 @@ TEST_F(CollisionTest, collision_box_box_dynamic_y_direction) {
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 2);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 2);
EXPECT_EQ(ev.info.resolution.x, -5);
EXPECT_EQ(ev.info.resolution.y, 5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -289,15 +286,13 @@ TEST_F(CollisionTest, collision_box_box_static_both) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, 10);
EXPECT_EQ(ev.info.resolution.y, 10);
EXPECT_EQ(ev.info.resolution_direction, crepe::CollisionSystem::Direction::BOTH);
};
- script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
- // is static should not be called
- FAIL();
- };
+ script_object2_ref->test_fn
+ = [&collision_happend](const CollisionEvent & ev) { collision_happend = true; };
EXPECT_FALSE(collision_happend);
Transform & tf = this->mgr.get_components_by_id<Transform>(1).front().get();
tf.position = {50, 30};
@@ -311,7 +306,7 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, -5);
EXPECT_EQ(ev.info.resolution.y, 5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -319,7 +314,7 @@ TEST_F(CollisionTest, collision_box_box_static_x_direction) {
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
// is static should not be called
- FAIL();
+ //FAIL();
};
EXPECT_FALSE(collision_happend);
Transform & tf = this->mgr.get_components_by_id<Transform>(1).front().get();
@@ -336,7 +331,7 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) {
bool collision_happend = false;
script_object1_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
+ EXPECT_EQ(ev.info.self.transform.game_object_id, 1);
EXPECT_EQ(ev.info.resolution.x, 5);
EXPECT_EQ(ev.info.resolution.y, -5);
EXPECT_EQ(ev.info.resolution_direction,
@@ -344,7 +339,7 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) {
};
script_object2_ref->test_fn = [&collision_happend](const CollisionEvent & ev) {
// is static should not be called
- FAIL();
+ //FAIL();
};
EXPECT_FALSE(collision_happend);
Transform & tf = this->mgr.get_components_by_id<Transform>(1).front().get();
@@ -356,37 +351,3 @@ TEST_F(CollisionTest, collision_box_box_static_y_direction) {
collision_sys.fixed_update();
EXPECT_TRUE(collision_happend);
}
-
-TEST_F(CollisionTest, collision_box_box_static_multiple) { //todo check visually
- bool collision_happend = false;
- float offset_value = 0;
- float resolution = 0;
- script_object1_ref->test_fn = [&](const CollisionEvent & ev) {
- collision_happend = true;
- EXPECT_EQ(ev.info.this_collider.game_object_id, 1);
- EXPECT_EQ(ev.info.this_collider.offset.x, offset_value);
- EXPECT_EQ(ev.info.resolution.x, resolution);
- };
- script_object2_ref->test_fn = [&](const CollisionEvent & ev) {
- // is static should not be called
- FAIL();
- };
- EXPECT_FALSE(collision_happend);
- Transform & tf = this->mgr.get_components_by_id<Transform>(1).front().get();
- tf.position = {45, 30};
- Rigidbody & rg1 = this->mgr.get_components_by_id<Rigidbody>(1).front().get();
- rg1.data.linear_velocity = {10, 10};
- Rigidbody & rg2 = this->mgr.get_components_by_id<Rigidbody>(2).front().get();
- rg2.data.body_type = crepe::Rigidbody::BodyType::STATIC;
- BoxCollider & bxc = this->mgr.get_components_by_id<BoxCollider>(1).front().get();
- bxc.offset = {5, 0};
- this->game_object1.add_component<BoxCollider>(vec2{-5, 0}, vec2{10, 10});
- offset_value = 5;
- resolution = 10;
- collision_sys.fixed_update();
- offset_value = -5;
- resolution = 10;
- tf.position = {55, 30};
- collision_sys.fixed_update();
- EXPECT_TRUE(collision_happend);
-}
diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp
index f988700..d1da5a0 100644
--- a/src/test/Profiling.cpp
+++ b/src/test/Profiling.cpp
@@ -32,7 +32,7 @@ using namespace testing;
class TestScript : public Script {
bool oncollision(const CollisionEvent & test) {
- Log::logf("Box {} script on_collision()", test.info.this_collider.game_object_id);
+ Log::logf("Box {} script on_collision()", test.info.self.transform.game_object_id);
return true;
}
void init() {
@@ -50,7 +50,7 @@ public:
// Minimum amount to let test pass
const int min_gameobject_count = 100;
// Maximum amount to stop test
- const int max_gameobject_count = 150;
+ const int max_gameobject_count = 3000;
// Amount of times a test runs to calculate average
const int average = 5;
// Maximum duration to stop test
@@ -61,6 +61,8 @@ public:
ResourceManager resman{m};
ComponentManager mgr{m};
// Add system used for profling tests
+ EventManager evmgr{m};
+ LoopTimerManager loopmgr{m};
CollisionSystem collision_sys{m};
PhysicsSystem physics_sys{m};
ParticleSystem particle_sys{m};