Wizard Engine
2D cross-platform game engine built around SDL2
 
Loading...
Searching...
No Matches
collider.hpp
Go to the documentation of this file.
1/*
2 Wizard Engine
3 Copyright (C) 2023-2024 Zana Domán
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#ifndef WIZARD_ENGINE_COLLIDER_HPP
23#define WIZARD_ENGINE_COLLIDER_HPP
24
29
30namespace wze {
31/*
32 * @file collider.hpp
33 * @author Zana Domán
34 * @brief Rigid entity.
35 */
36class collider : public entity {
37 private:
38 static std::array<std::vector<collider*>,
39 std::numeric_limits<uint8_t>::max()>
40 _worlds;
41 polygon _body;
42 float _force;
43 float _mass;
44 uint8_t _world;
45
54 template <void (collider::*static_resolver)(collider const&),
55 bool (collider::*dynamic_resolver)(collider&, float)>
56 // NOLINTNEXTLINE(misc-no-recursion)
57 void push(float force) {
58 std::vector<collider*> contacts;
59
60 contacts = collider::contacts();
61 if (contacts.empty()) {
62 return;
63 }
64
65 force -= contacts_mass(contacts);
66 if (0 < force) {
67 std::for_each(
68 contacts.begin(), contacts.end(),
69 // NOLINTNEXTLINE(misc-no-recursion)
70 [=](collider* contact) -> void {
71 if ((this->*dynamic_resolver)(*contact,
72 contact->mass() + force)) {
73 contact->push<static_resolver, dynamic_resolver>(force);
74 (this->*static_resolver)(*contact);
75 }
76 });
77 } else {
78 std::for_each(contacts.begin(), contacts.end(),
79 [=](collider const* contact) -> void {
80 (this->*static_resolver)(*contact);
81 });
82 }
83 }
84
91 [[nodiscard]] std::vector<collider*> contacts() const;
92
100 [[nodiscard]] static float
101 contacts_mass(std::vector<collider*> const& contacts);
102
113 template <float (polygon::*position)() const,
114 void (polygon::*set_position)(float)>
115 void solo_static_resolver(collider const& other) {
116 float collision;
117
118 collision = body().overlap<float>(other.body());
119 if (!(bool)collision) {
120 return;
121 }
122
123 collision += math::epsilon();
124 (_body.*set_position)((body().*position)() +
125 ((body().*position)() < (other.body().*position)()
126 ? -collision
127 : collision));
128 }
129
142 template <float (polygon::*position)() const,
143 void (polygon::*set_position)(float)>
144 [[nodiscard]] bool solo_dynamic_resolver(collider& other, float force) {
145 float collision;
146 std::pair<float, float> movement;
147
148 collision = body().overlap<float>(other.body());
149 if (!(bool)collision) {
150 return false;
151 }
152
153 movement = dynamic_movement(collision, force, other.mass());
154 if ((body().*position)() < (other.body().*position)()) {
155 (_body.*set_position)((body().*position)() - movement.first);
156 (other._body.*set_position)((other.body().*position)() +
157 movement.second);
158 } else {
159 (_body.*set_position)((body().*position)() + movement.first);
160 (other._body.*set_position)((other.body().*position)() -
161 movement.second);
162 }
163
164 return true;
165 }
166
174 void dual_static_resolver(collider const& other);
175
185 [[nodiscard]] bool dual_dynamic_resolver(collider& other, float force);
186
196 static std::pair<float, float> dynamic_movement(float collision,
197 float force, float mass);
198
204 void align_entities() const;
205
206 public:
213 [[nodiscard]] polygon const& body() const;
214
221 void set_body(polygon const& body);
222
229 [[nodiscard]] float force() const;
230
237 void set_force(float force);
238
245 [[nodiscard]] float mass() const;
246
253 void set_mass(float mass);
254
262 [[nodiscard]] uint8_t world() const;
263
271 void set_world(uint8_t world);
272
279 [[nodiscard]] float x() const final;
280
287 void set_x(float x) final;
288
295 [[nodiscard]] float y() const final;
296
303 void set_y(float y) final;
304
311 [[nodiscard]] float angle() const final;
312
319 void set_angle(float angle) final;
320
327 [[nodiscard]] float scale() const;
328
335 void set_scale(float scale);
336
343 [[nodiscard]] float x_offset() const final;
344
351 void set_x_offset(float x_offset) final;
352
359 [[nodiscard]] float y_offset() const final;
360
367 void set_y_offset(float y_offset) final;
368
375 [[nodiscard]] float angle_offset() const final;
376
383 void set_angle_offset(float angle_offset) final;
384
391 [[nodiscard]] bool attach_x() const final;
392
399 void set_attach_x(bool attach_x) final;
400
407 [[nodiscard]] bool attach_y() const final;
408
415 void set_attach_y(bool attach_y) final;
416
423 [[nodiscard]] bool attach_angle() const final;
424
431 void set_attach_angle(bool attach_angle) final;
432
439 [[nodiscard]] bool x_angle_lock() const final;
440
447 void set_x_angle_lock(bool x_angle_lock) final;
448
455 [[nodiscard]] bool y_angle_lock() const final;
456
463 void set_y_angle_lock(bool y_angle_lock) final;
464
476 explicit collider(
477 polygon const& body = polygon(), float force = 0, float mass = 0,
478 uint8_t world = std::numeric_limits<uint8_t>::max(),
479 std::vector<std::weak_ptr<component>> const& components = {});
480
487 collider(collider const& other);
488
494 ~collider() override;
495
503 collider& operator=(collider const& other);
504};
505} /* namespace wze */
506
507#endif /* WIZARD_ENGINE_COLLIDER_HPP */
static constexpr float epsilon()
Single precision epsilon.
Definition math.hpp:47
Composes composable objects.
Export header of the Wizard Engine.
Math modul.
Wizard Engine.
Convex polygon component.