4 #include "game/camera.h"
5 #include "game/level/platforms.h"
7 #include "system/nth_alloc.h"
8 #include "system/stacktrace.h"
9 #include "system/line_stream.h"
10 #include "system/str.h"
11 #include "system/log.h"
14 #include "./rigid_bodies.h"
31 RigidBodies *create_rigid_bodies(size_t capacity)
35 RigidBodies *rigid_bodies = PUSH_LT(lt, nth_calloc(1, sizeof(RigidBodies)), free);
36 if (rigid_bodies == NULL) {
39 rigid_bodies->lt = lt;
41 rigid_bodies->capacity = capacity;
42 rigid_bodies->count = 0;
44 rigid_bodies->bodies = PUSH_LT(lt, nth_calloc(capacity, sizeof(Rect)), free);
45 if (rigid_bodies->bodies == NULL) {
49 rigid_bodies->velocities = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
50 if (rigid_bodies->velocities == NULL) {
54 rigid_bodies->movements = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
55 if (rigid_bodies->movements == NULL) {
59 rigid_bodies->grounded = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
60 if (rigid_bodies->grounded == NULL) {
64 rigid_bodies->forces = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
65 if (rigid_bodies->forces == NULL) {
69 rigid_bodies->deleted = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
70 if (rigid_bodies->deleted == NULL) {
74 rigid_bodies->disabled = PUSH_LT(
76 nth_calloc(capacity, sizeof(bool)),
78 if (rigid_bodies->disabled == NULL) {
85 void destroy_rigid_bodies(RigidBodies *rigid_bodies)
87 trace_assert(rigid_bodies);
88 RETURN_LT0(rigid_bodies->lt);
91 int rigid_bodies_collide(RigidBodies *rigid_bodies,
92 const Platforms *platforms)
94 // TODO(#683): RigidBodies should collide only the bodies that were updated on after a previous collision
95 memset(rigid_bodies->grounded, 0, sizeof(bool) * rigid_bodies->count);
97 if (rigid_bodies->count == 0) {
101 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
105 int the_variable_that_gets_set_when_a_collision_happens_xd = 1;
106 while (t-- > 0 && the_variable_that_gets_set_when_a_collision_happens_xd) {
107 the_variable_that_gets_set_when_a_collision_happens_xd = 0;
109 for (size_t i1 = 0; i1 < rigid_bodies->count; ++i1) {
110 if (rigid_bodies->deleted[i1] || rigid_bodies->disabled[i1]) {
115 memset(sides, 0, sizeof(int) * RECT_SIDE_N);
117 platforms_touches_rect_sides(platforms, rigid_bodies->bodies[i1], sides);
119 for (int i = 0; i < RECT_SIDE_N; ++i) {
121 the_variable_that_gets_set_when_a_collision_happens_xd = 1;
125 if (sides[RECT_SIDE_BOTTOM]) {
126 rigid_bodies->grounded[i1] = true;
129 Vec v = platforms_snap_rect(platforms, &rigid_bodies->bodies[i1]);
130 rigid_bodies->velocities[i1] = vec_entry_mult(rigid_bodies->velocities[i1], v);
131 rigid_bodies->movements[i1] = vec_entry_mult(rigid_bodies->movements[i1], v);
132 rigid_bodies_damper(rigid_bodies, i1, vec_entry_mult(v, vec(-16.0f, 0.0f)));
134 if (i1 >= rigid_bodies->count - 1) {
139 for (size_t i2 = i1 + 1; i2 < rigid_bodies->count; ++i2) {
140 if (rigid_bodies->deleted[i2] || rigid_bodies->disabled[i1]) {
144 if (!rects_overlap(rigid_bodies->bodies[i1], rigid_bodies->bodies[i2])) {
148 the_variable_that_gets_set_when_a_collision_happens_xd = 1;
150 Vec orient = rect_impulse(&rigid_bodies->bodies[i1], &rigid_bodies->bodies[i2]);
152 if (orient.x > orient.y) {
153 if (rigid_bodies->bodies[i1].y < rigid_bodies->bodies[i2].y) {
154 rigid_bodies->grounded[i1] = true;
156 rigid_bodies->grounded[i2] = true;
160 rigid_bodies->velocities[i1] = vec(rigid_bodies->velocities[i1].x * orient.x, rigid_bodies->velocities[i1].y * orient.y);
161 rigid_bodies->velocities[i2] = vec(rigid_bodies->velocities[i2].x * orient.x, rigid_bodies->velocities[i2].y * orient.y);
162 rigid_bodies->movements[i1] = vec(rigid_bodies->movements[i1].x * orient.x, rigid_bodies->movements[i1].y * orient.y);
163 rigid_bodies->movements[i2] = vec(rigid_bodies->movements[i2].x * orient.x, rigid_bodies->movements[i2].y * orient.y);
171 int rigid_bodies_update(RigidBodies *rigid_bodies,
175 trace_assert(rigid_bodies);
177 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
181 rigid_bodies->velocities[id] = vec_sum(
182 rigid_bodies->velocities[id],
184 rigid_bodies->forces[id],
187 Vec position = vec(rigid_bodies->bodies[id].x,
188 rigid_bodies->bodies[id].y);
194 rigid_bodies->velocities[id],
195 rigid_bodies->movements[id]),
198 rigid_bodies->bodies[id].x = position.x;
199 rigid_bodies->bodies[id].y = position.y;
201 rigid_bodies->forces[id] = vec(0.0f, 0.0f);
206 int rigid_bodies_render(RigidBodies *rigid_bodies,
211 trace_assert(rigid_bodies);
212 trace_assert(camera);
214 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
218 char text_buffer[256];
220 if (camera_fill_rect(
222 rigid_bodies->bodies[id],
227 snprintf(text_buffer, 256, "id: %zd", id);
229 if (camera_render_debug_text(
232 vec(rigid_bodies->bodies[id].x,
233 rigid_bodies->bodies[id].y)) < 0) {
237 snprintf(text_buffer, 256, "p:(%.2f, %.2f)",
238 rigid_bodies->bodies[id].x,
239 rigid_bodies->bodies[id].y);
240 if (camera_render_debug_text(
243 vec(rigid_bodies->bodies[id].x,
244 rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 2.0f))) {
248 snprintf(text_buffer, 256, "v:(%.2f, %.2f)",
249 rigid_bodies->velocities[id].x,
250 rigid_bodies->velocities[id].y);
251 if (camera_render_debug_text(
254 vec(rigid_bodies->bodies[id].x,
255 rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 4.0f))) {
259 snprintf(text_buffer, 256, "m:(%.2f, %.2f)",
260 rigid_bodies->movements[id].x,
261 rigid_bodies->movements[id].y);
262 if (camera_render_debug_text(
265 vec(rigid_bodies->bodies[id].x,
266 rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 6.0f))) {
273 RigidBodyId rigid_bodies_add(RigidBodies *rigid_bodies,
276 trace_assert(rigid_bodies);
277 trace_assert(rigid_bodies->count < rigid_bodies->capacity);
279 RigidBodyId id = rigid_bodies->count++;
280 rigid_bodies->bodies[id] = rect;
285 void rigid_bodies_remove(RigidBodies *rigid_bodies,
288 trace_assert(rigid_bodies);
289 trace_assert(id < rigid_bodies->capacity);
291 rigid_bodies->deleted[id] = true;
294 Rect rigid_bodies_hitbox(const RigidBodies *rigid_bodies,
297 trace_assert(rigid_bodies);
298 trace_assert(id < rigid_bodies->count);
300 return rigid_bodies->bodies[id];
303 void rigid_bodies_move(RigidBodies *rigid_bodies,
307 trace_assert(rigid_bodies);
308 trace_assert(id < rigid_bodies->count);
310 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
314 rigid_bodies->movements[id] = movement;
317 int rigid_bodies_touches_ground(const RigidBodies *rigid_bodies,
320 trace_assert(rigid_bodies);
321 trace_assert(id < rigid_bodies->count);
323 return rigid_bodies->grounded[id];
326 void rigid_bodies_apply_omniforce(RigidBodies *rigid_bodies,
329 for (size_t i = 0; i < rigid_bodies->count; ++i) {
330 rigid_bodies_apply_force(rigid_bodies, i, force);
334 void rigid_bodies_apply_force(RigidBodies * rigid_bodies,
338 trace_assert(rigid_bodies);
339 trace_assert(id < rigid_bodies->count);
341 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
345 rigid_bodies->forces[id] = vec_sum(rigid_bodies->forces[id], force);
348 void rigid_bodies_transform_velocity(RigidBodies *rigid_bodies,
352 trace_assert(rigid_bodies);
353 trace_assert(id < rigid_bodies->count);
355 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
359 rigid_bodies->velocities[id] = point_mat3x3_product(
360 rigid_bodies->velocities[id],
364 void rigid_bodies_teleport_to(RigidBodies *rigid_bodies,
368 trace_assert(rigid_bodies);
369 trace_assert(id < rigid_bodies->count);
371 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
375 rigid_bodies->bodies[id].x = position.x;
376 rigid_bodies->bodies[id].y = position.y;
379 void rigid_bodies_damper(RigidBodies *rigid_bodies,
383 trace_assert(rigid_bodies);
384 trace_assert(id < rigid_bodies->count);
386 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
390 rigid_bodies_apply_force(
393 rigid_bodies->velocities[id].x * v.x,
394 rigid_bodies->velocities[id].y * v.y));
397 void rigid_bodies_disable(RigidBodies *rigid_bodies,
401 trace_assert(rigid_bodies);
402 trace_assert(id < rigid_bodies->count);
404 rigid_bodies->disabled[id] = disabled;