27 template<
typename... Hitboxes>
requires (std::derived_from<Hitboxes, Hitbox> && ...)
28 Universe(std::vector<Field*> fields, Hitboxes&... hitboxes) : fields{ fields } {
29 (bodies.push_back(&hitboxes), ...);
41 calculateFieldForces();
44 collisionDetection(elapsedSeconds);
47 applyForces(elapsedSeconds);
52 bodies.push_back(&body);
56 bodies.erase(std::remove(bodies.begin(), bodies.end(), &body), bodies.end());
63 void calculateFieldForces() {
64 for (
auto body : bodies) {
65 for (
auto field : fields) {
66 body->addExternalForce(field->calculateAppliedForce(*body));
73 void collisionDetection(Time elapsedSeconds) {
74 for (
int i = 0; i < bodies.size(); ++i) {
75 for (
int j = i + 1; j < bodies.size(); ++j) {
79 if (
typeid(*bodies[i]) ==
typeid(CircleHitbox) &&
typeid(*bodies[j]) ==
typeid(CircleHitbox)) {
80 CircleHitbox& c1 =
static_cast<CircleHitbox&
>(*bodies[i]);
81 CircleHitbox& c2 =
static_cast<CircleHitbox&
>(*bodies[j]);
82 collisionDetection(c2, c1, elapsedSeconds);
86 else if (
typeid(*bodies[i]) ==
typeid(FrameHitbox) &&
typeid(*bodies[j]) ==
typeid(CircleHitbox)) {
87 FrameHitbox& f1 =
static_cast<FrameHitbox&
>(*bodies[i]);
88 CircleHitbox& c2 =
static_cast<CircleHitbox&
>(*bodies[j]);
89 collisionDetection(f1, c2, elapsedSeconds);
93 else if (
typeid(*bodies[i]) ==
typeid(CircleHitbox) &&
typeid(*bodies[j]) ==
typeid(FrameHitbox)) {
94 CircleHitbox& c1 =
static_cast<CircleHitbox&
>(*bodies[i]);
95 FrameHitbox& f2 =
static_cast<FrameHitbox&
>(*bodies[j]);
96 collisionDetection(f2, c1, elapsedSeconds);
104 void applyForces(Time elapsedSeconds) {
105 for (
auto body : bodies) {
106 body->move(elapsedSeconds);
113 static void collisionDetection(CircleHitbox& c1, CircleHitbox& c2, Time elapsedSeconds) {
114 auto distance = c1.getPosition() - c2.getPosition();
115 if ( distance <= c1.getRadius() + c2.getRadius()) {
117 auto s1 = c1.getSpeed();
auto s2 = c2.getSpeed();
118 auto m1 = c1.getMass();
auto m2 = c2.getMass();
120 auto n = glm::normalize(glm::vec3(c1.getPosition() - c2.getPosition()));
122 auto impulse = float((s2 - s1) * n * (-e - 1) * ((m1 * m2) / (m1 + m2)));
125 c1.addExternalForce(-(impulse * n) / elapsedSeconds);
126 c2.addExternalForce((impulse * n) / elapsedSeconds);
134 static void collisionDetection(FrameHitbox& f, CircleHitbox& c, Time elapsedSeconds) {
135 bool haveCollided =
false;
137 for (
int i = 0; i < f.getNumberOfSegments(); ++i) {
139 if (segment.distance(c.getPosition()) <= c.getRadius()) {
141 auto s1 = c.getSpeed();
auto s2 = f.getSpeed();
142 auto m1 = c.getMass();
auto m2 = f.getMass();
144 auto n = segment.normal(c.getPosition());
147 auto sr2 = f.getAngularSpeed();
148 auto distanceFromCenterOfRotation = glm::length(glm::vec3((c.getPosition() + n * c.getRadius()) - f.getPosition()));
150 auto tangentialSpeed = Speed(-segment.normal() * (sr2 * distanceFromCenterOfRotation)) * 1.1f;
151 auto massCoefficient = (m1 * m2) / (m1 + m2);
152 auto impulse = float(((s2 + tangentialSpeed - s1) * n) * (-e - 1) * massCoefficient);
154 f.addExternalForce((impulse * glm::vec3(n)) / elapsedSeconds);
155 c.addExternalForce(-(impulse * glm::vec3(n)) / elapsedSeconds);
170 std::vector<Hitbox*> bodies;
171 std::vector<Field*> fields;
A Hitbox is a Cinematicable object which can directly interact with other objects upon collision.
Definition: Hitbox.h:19
A Universe is a container of Hitbox(es) and Field(s).
Definition: Universe.h:18
Universe(std::vector< Field * > fields, Hitboxes &... hitboxes)
Builds an isolated Universe.
Definition: Universe.h:28
void removeBody(Hitbox &body)
Definition: Universe.h:55
void calculate(float elapsedSeconds)
Calculates the new position of all the objects in the universe, their interaction with the other obje...
Definition: Universe.h:39
void addBody(Hitbox &body)
Definition: Universe.h:51
Definition: Cinematicable.h:9