#include "system/lt.h"
#include "system/nth_alloc.h"
#include "system/stacktrace.h"
+#include "system/line_stream.h"
+#include "system/str.h"
+#include "system/log.h"
+#include "hashset.h"
#include "./rigid_bodies.h"
size_t capacity;
size_t count;
- Vec *positions;
- Vec *velocities;
- Vec *movements;
- Vec *sizes;
- Color *colors;
+ Rect *bodies;
+ Vec2f *velocities;
+ Vec2f *movements;
bool *grounded;
- Vec *forces;
+ Vec2f *forces;
+ bool *deleted;
+ bool *disabled;
};
-static const Vec opposing_rect_side_forces[RECT_SIDE_N] = {
- { .x = 1.0f, .y = 0.0f }, /* RECT_SIDE_LEFT = 0, */
- { .x = -1.0f, .y = 0.0f }, /* RECT_SIDE_RIGHT, */
- { .x = 0.0f, .y = 1.0f, }, /* RECT_SIDE_TOP, */
- { .x = 0.0f, .y = -1.0f, } /* RECT_SIDE_BOTTOM, */
-};
-
-static Vec opposing_force_by_sides(int sides[RECT_SIDE_N])
-{
- Vec opposing_force = {
- .x = 0.0f,
- .y = 0.0f
- };
-
- for (Rect_side side = 0; side < RECT_SIDE_N; ++side) {
- if (sides[side]) {
- vec_add(
- &opposing_force,
- opposing_rect_side_forces[side]);
- }
- }
-
- return opposing_force;
-}
-
RigidBodies *create_rigid_bodies(size_t capacity)
{
Lt *lt = create_lt();
- if (lt == NULL) {
- return NULL;
- }
RigidBodies *rigid_bodies = PUSH_LT(lt, nth_calloc(1, sizeof(RigidBodies)), free);
if (rigid_bodies == NULL) {
rigid_bodies->capacity = capacity;
rigid_bodies->count = 0;
- rigid_bodies->positions = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
- if (rigid_bodies->positions == NULL) {
+ rigid_bodies->bodies = PUSH_LT(lt, nth_calloc(capacity, sizeof(Rect)), free);
+ if (rigid_bodies->bodies == NULL) {
RETURN_LT(lt, NULL);
}
- rigid_bodies->velocities = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
+ rigid_bodies->velocities = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec2f)), free);
if (rigid_bodies->velocities == NULL) {
RETURN_LT(lt, NULL);
}
- rigid_bodies->movements = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
+ rigid_bodies->movements = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec2f)), free);
if (rigid_bodies->movements == NULL) {
RETURN_LT(lt, NULL);
}
- rigid_bodies->sizes = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
- if (rigid_bodies->sizes == NULL) {
+ rigid_bodies->grounded = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
+ if (rigid_bodies->grounded == NULL) {
RETURN_LT(lt, NULL);
}
- rigid_bodies->colors = PUSH_LT(lt, nth_calloc(capacity, sizeof(Color)), free);
- if (rigid_bodies->colors == NULL) {
+ rigid_bodies->forces = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec2f)), free);
+ if (rigid_bodies->forces == NULL) {
RETURN_LT(lt, NULL);
}
- rigid_bodies->grounded = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
- if (rigid_bodies->grounded == NULL) {
+ rigid_bodies->deleted = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
+ if (rigid_bodies->deleted == NULL) {
RETURN_LT(lt, NULL);
}
- rigid_bodies->forces = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
- if (rigid_bodies->forces == NULL) {
+ rigid_bodies->disabled = PUSH_LT(
+ lt,
+ nth_calloc(capacity, sizeof(bool)),
+ free);
+ if (rigid_bodies->disabled == NULL) {
RETURN_LT(lt, NULL);
}
RETURN_LT0(rigid_bodies->lt);
}
-static int rigid_bodies_collide_with_itself(RigidBodies *rigid_bodies)
+int rigid_bodies_collide(RigidBodies *rigid_bodies,
+ const Platforms *platforms)
{
- trace_assert(rigid_bodies);
+ memset(rigid_bodies->grounded, 0, sizeof(bool) * rigid_bodies->count);
if (rigid_bodies->count == 0) {
return 0;
}
- for (size_t i1 = 0; i1 < rigid_bodies->count - 1; ++i1) {
- for (size_t i2 = i1 + 1; i2 < rigid_bodies->count; ++i2) {
- // TODO(#653): Rigid Bodies perform too many conversions between rect and two vecs representation
- // Maybe it's just better to represent the bodies as rects all the time?
- // TODO(#654): Rigid Bodies don't exchange forces with each other
+ int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
+
- Rect r1 = rect_from_vecs(rigid_bodies->positions[i1], rigid_bodies->sizes[i1]);
- Rect r2 = rect_from_vecs(rigid_bodies->positions[i2], rigid_bodies->sizes[i2]);
+ int t = 100;
+ int the_variable_that_gets_set_when_a_collision_happens_xd = 1;
+ while (t-- > 0 && the_variable_that_gets_set_when_a_collision_happens_xd) {
+ the_variable_that_gets_set_when_a_collision_happens_xd = 0;
- if (!rects_overlap(r1, r2)) {
+ for (size_t i1 = 0; i1 < rigid_bodies->count; ++i1) {
+ if (rigid_bodies->deleted[i1] || rigid_bodies->disabled[i1]) {
continue;
}
- rect_impulse(&r1, &r2);
-
- rigid_bodies->positions[i1] = vec(r1.x, r1.y);
- rigid_bodies->sizes[i1] = vec(r1.w, r1.h);
-
- rigid_bodies->positions[i2] = vec(r2.x, r2.y);
- rigid_bodies->sizes[i2] = vec(r2.w, r2.h);
- }
- }
+ // Platforms
+ memset(sides, 0, sizeof(int) * RECT_SIDE_N);
- return 0;
-}
+ platforms_touches_rect_sides(platforms, rigid_bodies->bodies[i1], sides);
-static int rigid_bodies_collide_with_platforms(
- RigidBodies *rigid_bodies,
- const Platforms *platforms)
-{
- trace_assert(rigid_bodies);
- trace_assert(platforms);
+ for (int i = 0; i < RECT_SIDE_N; ++i) {
+ if (sides[i]) {
+ the_variable_that_gets_set_when_a_collision_happens_xd = 1;
+ }
+ }
- int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
+ if (sides[RECT_SIDE_BOTTOM]) {
+ rigid_bodies->grounded[i1] = true;
+ }
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- memset(sides, 0, sizeof(int) * RECT_SIDE_N);
+ Vec2f v = platforms_snap_rect(platforms, &rigid_bodies->bodies[i1]);
+ rigid_bodies->velocities[i1] = vec_entry_mult(rigid_bodies->velocities[i1], v);
+ rigid_bodies->movements[i1] = vec_entry_mult(rigid_bodies->movements[i1], v);
+ rigid_bodies_damper(rigid_bodies, i1, vec_entry_mult(v, vec(-16.0f, 0.0f)));
- Rect hitbox = rigid_bodies_hitbox(rigid_bodies, i);
+ if (i1 >= rigid_bodies->count - 1) {
+ continue;
+ }
- platforms_touches_rect_sides(platforms, hitbox, sides);
+ // Self-collision
+ for (size_t i2 = i1 + 1; i2 < rigid_bodies->count; ++i2) {
+ if (rigid_bodies->deleted[i2] || rigid_bodies->disabled[i1]) {
+ continue;
+ }
- if (sides[RECT_SIDE_BOTTOM]) {
- rigid_bodies->grounded[i] = true;
- }
+ if (!rects_overlap(rigid_bodies->bodies[i1], rigid_bodies->bodies[i2])) {
+ continue;
+ }
- /* TODO(#655): Opposing force notion in Rigid Bodies seems redundant */
- Vec opforce_direction = opposing_force_by_sides(sides);
+ the_variable_that_gets_set_when_a_collision_happens_xd = 1;
- if (fabs(opforce_direction.x) > 1e-6 && (opforce_direction.x < 0.0f) != ((rigid_bodies->velocities[i].x + rigid_bodies->movements[i].x) < 0.0f)) {
- rigid_bodies->velocities[i].x = 0.0f;
- rigid_bodies->movements[i].x = 0.0f;
- }
+ Vec2f orient = rect_impulse(&rigid_bodies->bodies[i1], &rigid_bodies->bodies[i2]);
- if (fabs(opforce_direction.y) > 1e-6 && (opforce_direction.y < 0.0f) != ((rigid_bodies->velocities[i].y + rigid_bodies->movements[i].y) < 0.0f)) {
- rigid_bodies->velocities[i].y = 0.0f;
- rigid_bodies->movements[i].y = 0.0f;
+ if (orient.x > orient.y) {
+ if (rigid_bodies->bodies[i1].y < rigid_bodies->bodies[i2].y) {
+ rigid_bodies->grounded[i1] = true;
+ } else {
+ rigid_bodies->grounded[i2] = true;
+ }
+ }
- if (vec_length(rigid_bodies->velocities[i]) > 1e-6) {
- rigid_bodies_apply_force(
- rigid_bodies, i,
- vec_scala_mult(
- vec_neg(rigid_bodies->velocities[i]),
- 16.0f));
+ rigid_bodies->velocities[i1] = vec(rigid_bodies->velocities[i1].x * orient.x, rigid_bodies->velocities[i1].y * orient.y);
+ rigid_bodies->velocities[i2] = vec(rigid_bodies->velocities[i2].x * orient.x, rigid_bodies->velocities[i2].y * orient.y);
+ rigid_bodies->movements[i1] = vec(rigid_bodies->movements[i1].x * orient.x, rigid_bodies->movements[i1].y * orient.y);
+ rigid_bodies->movements[i2] = vec(rigid_bodies->movements[i2].x * orient.x, rigid_bodies->movements[i2].y * orient.y);
}
}
-
- hitbox = platforms_snap_rect(platforms, hitbox);
- rigid_bodies->positions[i].x = hitbox.x;
- rigid_bodies->positions[i].y = hitbox.y;
- }
-
- return 0;
-}
-
-int rigid_bodies_collide(RigidBodies *rigid_bodies,
- const Platforms *platforms)
-{
- if (rigid_bodies_collide_with_itself(rigid_bodies) < 0) {
- return -1;
- }
-
- if (rigid_bodies_collide_with_platforms(rigid_bodies, platforms) < 0) {
- return -1;
}
return 0;
}
int rigid_bodies_update(RigidBodies *rigid_bodies,
+ RigidBodyId id,
float delta_time)
{
trace_assert(rigid_bodies);
- memset(rigid_bodies->grounded, 0,
- sizeof(bool) * rigid_bodies->count);
-
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- rigid_bodies->velocities[i] = vec_sum(
- rigid_bodies->velocities[i],
- vec_scala_mult(
- rigid_bodies->forces[i],
- delta_time));
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return 0;
}
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- rigid_bodies->positions[i] = vec_sum(
- rigid_bodies->positions[i],
+ rigid_bodies->velocities[id] = vec_sum(
+ rigid_bodies->velocities[id],
vec_scala_mult(
- vec_sum(
- rigid_bodies->velocities[i],
- rigid_bodies->movements[i]),
+ rigid_bodies->forces[id],
delta_time));
- }
- memset(rigid_bodies->forces, 0,
- sizeof(Vec) * rigid_bodies->count);
+ Vec2f position = vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y);
+
+ position = vec_sum(
+ position,
+ vec_scala_mult(
+ vec_sum(
+ rigid_bodies->velocities[id],
+ rigid_bodies->movements[id]),
+ delta_time));
+
+ rigid_bodies->bodies[id].x = position.x;
+ rigid_bodies->bodies[id].y = position.y;
+
+ rigid_bodies->forces[id] = vec(0.0f, 0.0f);
return 0;
}
int rigid_bodies_render(RigidBodies *rigid_bodies,
- Camera *camera)
+ RigidBodyId id,
+ Color color,
+ const Camera *camera)
{
trace_assert(rigid_bodies);
trace_assert(camera);
- /* TODO: Rigid Bodies don't render their ids in the debug mode */
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return 0;
+ }
- for (size_t i = 0; i < rigid_bodies->count; ++i) {
- if (camera_fill_rect(
- camera,
- rect_from_vecs(
- rigid_bodies->positions[i],
- rigid_bodies->sizes[i]),
- rigid_bodies->colors[i]) < 0) {
- return -1;
- }
+ char text_buffer[256];
+
+ if (camera_fill_rect(
+ camera,
+ rigid_bodies->bodies[id],
+ color) < 0) {
+ return -1;
+ }
+
+ snprintf(text_buffer, 256, "id: %zd", id);
+
+ if (camera_render_debug_text(
+ camera,
+ text_buffer,
+ vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y)) < 0) {
+ return -1;
+ }
+
+ snprintf(text_buffer, 256, "p:(%.2f, %.2f)",
+ rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y);
+ if (camera_render_debug_text(
+ camera,
+ text_buffer,
+ vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 2.0f))) {
+ return -1;
+ }
+
+ snprintf(text_buffer, 256, "v:(%.2f, %.2f)",
+ rigid_bodies->velocities[id].x,
+ rigid_bodies->velocities[id].y);
+ if (camera_render_debug_text(
+ camera,
+ text_buffer,
+ vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 4.0f))) {
+ return -1;
+ }
+
+ snprintf(text_buffer, 256, "m:(%.2f, %.2f)",
+ rigid_bodies->movements[id].x,
+ rigid_bodies->movements[id].y);
+ if (camera_render_debug_text(
+ camera,
+ text_buffer,
+ vec(rigid_bodies->bodies[id].x,
+ rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 6.0f))) {
+ return -1;
}
return 0;
}
RigidBodyId rigid_bodies_add(RigidBodies *rigid_bodies,
- Rect rect,
- Color color)
+ Rect rect)
{
trace_assert(rigid_bodies);
trace_assert(rigid_bodies->count < rigid_bodies->capacity);
RigidBodyId id = rigid_bodies->count++;
- rigid_bodies->positions[id] = vec(rect.x, rect.y);
- rigid_bodies->sizes[id] = vec(rect.w, rect.h);
- rigid_bodies->colors[id] = color;
+ rigid_bodies->bodies[id] = rect;
return id;
}
+void rigid_bodies_remove(RigidBodies *rigid_bodies,
+ RigidBodyId id)
+{
+ trace_assert(rigid_bodies);
+ trace_assert(id < rigid_bodies->capacity);
+
+ rigid_bodies->deleted[id] = true;
+}
+
Rect rigid_bodies_hitbox(const RigidBodies *rigid_bodies,
RigidBodyId id)
{
trace_assert(rigid_bodies);
trace_assert(id < rigid_bodies->count);
- return rect_from_vecs(rigid_bodies->positions[id],
- rigid_bodies->sizes[id]);
+ return rigid_bodies->bodies[id];
}
void rigid_bodies_move(RigidBodies *rigid_bodies,
RigidBodyId id,
- Vec movement)
+ Vec2f movement)
{
trace_assert(rigid_bodies);
trace_assert(id < rigid_bodies->count);
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return;
+ }
+
rigid_bodies->movements[id] = movement;
}
}
void rigid_bodies_apply_omniforce(RigidBodies *rigid_bodies,
- Vec force)
+ Vec2f force)
{
for (size_t i = 0; i < rigid_bodies->count; ++i) {
rigid_bodies_apply_force(rigid_bodies, i, force);
void rigid_bodies_apply_force(RigidBodies * rigid_bodies,
RigidBodyId id,
- Vec force)
+ Vec2f force)
{
trace_assert(rigid_bodies);
trace_assert(id < rigid_bodies->count);
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return;
+ }
+
rigid_bodies->forces[id] = vec_sum(rigid_bodies->forces[id], force);
}
trace_assert(rigid_bodies);
trace_assert(id < rigid_bodies->count);
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return;
+ }
+
rigid_bodies->velocities[id] = point_mat3x3_product(
rigid_bodies->velocities[id],
trans_mat);
void rigid_bodies_teleport_to(RigidBodies *rigid_bodies,
RigidBodyId id,
- Vec position)
+ Vec2f position)
{
trace_assert(rigid_bodies);
trace_assert(id < rigid_bodies->count);
- rigid_bodies->positions[id] = position;
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return;
+ }
+
+ rigid_bodies->bodies[id].x = position.x;
+ rigid_bodies->bodies[id].y = position.y;
}
void rigid_bodies_damper(RigidBodies *rigid_bodies,
RigidBodyId id,
- Vec v)
+ Vec2f v)
{
trace_assert(rigid_bodies);
trace_assert(id < rigid_bodies->count);
+ if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
+ return;
+ }
+
rigid_bodies_apply_force(
rigid_bodies, id,
vec(
rigid_bodies->velocities[id].x * v.x,
rigid_bodies->velocities[id].y * v.y));
}
+
+void rigid_bodies_disable(RigidBodies *rigid_bodies,
+ RigidBodyId id,
+ bool disabled)
+{
+ trace_assert(rigid_bodies);
+ trace_assert(id < rigid_bodies->count);
+
+ rigid_bodies->disabled[id] = disabled;
+}