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"
13 #include "./rigid_bodies.h"
30 RigidBodies *create_rigid_bodies(size_t capacity)
34 RigidBodies *rigid_bodies = PUSH_LT(lt, nth_calloc(1, sizeof(RigidBodies)), free);
35 if (rigid_bodies == NULL) {
38 rigid_bodies->lt = lt;
40 rigid_bodies->capacity = capacity;
41 rigid_bodies->count = 0;
43 rigid_bodies->bodies = PUSH_LT(lt, nth_calloc(capacity, sizeof(Rect)), free);
44 if (rigid_bodies->bodies == NULL) {
48 rigid_bodies->velocities = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec2f)), free);
49 if (rigid_bodies->velocities == NULL) {
53 rigid_bodies->movements = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec2f)), free);
54 if (rigid_bodies->movements == NULL) {
58 rigid_bodies->grounded = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
59 if (rigid_bodies->grounded == NULL) {
63 rigid_bodies->forces = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec2f)), free);
64 if (rigid_bodies->forces == NULL) {
68 rigid_bodies->deleted = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
69 if (rigid_bodies->deleted == NULL) {
73 rigid_bodies->disabled = PUSH_LT(
75 nth_calloc(capacity, sizeof(bool)),
77 if (rigid_bodies->disabled == NULL) {
84 void destroy_rigid_bodies(RigidBodies *rigid_bodies)
86 trace_assert(rigid_bodies);
87 RETURN_LT0(rigid_bodies->lt);
90 int rigid_bodies_collide(RigidBodies *rigid_bodies,
91 const Platforms *platforms)
93 memset(rigid_bodies->grounded, 0, sizeof(bool) * rigid_bodies->count);
95 if (rigid_bodies->count == 0) {
99 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
103 int the_variable_that_gets_set_when_a_collision_happens_xd = 1;
104 while (t-- > 0 && the_variable_that_gets_set_when_a_collision_happens_xd) {
105 the_variable_that_gets_set_when_a_collision_happens_xd = 0;
107 for (size_t i1 = 0; i1 < rigid_bodies->count; ++i1) {
108 if (rigid_bodies->deleted[i1] || rigid_bodies->disabled[i1]) {
113 memset(sides, 0, sizeof(int) * RECT_SIDE_N);
115 platforms_touches_rect_sides(platforms, rigid_bodies->bodies[i1], sides);
117 for (int i = 0; i < RECT_SIDE_N; ++i) {
119 the_variable_that_gets_set_when_a_collision_happens_xd = 1;
123 if (sides[RECT_SIDE_BOTTOM]) {
124 rigid_bodies->grounded[i1] = true;
127 Vec2f v = platforms_snap_rect(platforms, &rigid_bodies->bodies[i1]);
128 rigid_bodies->velocities[i1] = vec_entry_mult(rigid_bodies->velocities[i1], v);
129 rigid_bodies->movements[i1] = vec_entry_mult(rigid_bodies->movements[i1], v);
130 rigid_bodies_damper(rigid_bodies, i1, vec_entry_mult(v, vec(-16.0f, 0.0f)));
132 if (i1 >= rigid_bodies->count - 1) {
137 for (size_t i2 = i1 + 1; i2 < rigid_bodies->count; ++i2) {
138 if (rigid_bodies->deleted[i2] || rigid_bodies->disabled[i1]) {
142 if (!rects_overlap(rigid_bodies->bodies[i1], rigid_bodies->bodies[i2])) {
146 the_variable_that_gets_set_when_a_collision_happens_xd = 1;
148 Vec2f orient = rect_impulse(&rigid_bodies->bodies[i1], &rigid_bodies->bodies[i2]);
150 if (orient.x > orient.y) {
151 if (rigid_bodies->bodies[i1].y < rigid_bodies->bodies[i2].y) {
152 rigid_bodies->grounded[i1] = true;
154 rigid_bodies->grounded[i2] = true;
158 rigid_bodies->velocities[i1] = vec(rigid_bodies->velocities[i1].x * orient.x, rigid_bodies->velocities[i1].y * orient.y);
159 rigid_bodies->velocities[i2] = vec(rigid_bodies->velocities[i2].x * orient.x, rigid_bodies->velocities[i2].y * orient.y);
160 rigid_bodies->movements[i1] = vec(rigid_bodies->movements[i1].x * orient.x, rigid_bodies->movements[i1].y * orient.y);
161 rigid_bodies->movements[i2] = vec(rigid_bodies->movements[i2].x * orient.x, rigid_bodies->movements[i2].y * orient.y);
169 int rigid_bodies_update(RigidBodies *rigid_bodies,
173 trace_assert(rigid_bodies);
175 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
179 rigid_bodies->velocities[id] = vec_sum(
180 rigid_bodies->velocities[id],
182 rigid_bodies->forces[id],
185 Vec2f position = vec(rigid_bodies->bodies[id].x,
186 rigid_bodies->bodies[id].y);
192 rigid_bodies->velocities[id],
193 rigid_bodies->movements[id]),
196 rigid_bodies->bodies[id].x = position.x;
197 rigid_bodies->bodies[id].y = position.y;
199 rigid_bodies->forces[id] = vec(0.0f, 0.0f);
204 int rigid_bodies_render(RigidBodies *rigid_bodies,
207 const Camera *camera)
209 trace_assert(rigid_bodies);
210 trace_assert(camera);
212 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
216 char text_buffer[256];
218 if (camera_fill_rect(
220 rigid_bodies->bodies[id],
225 snprintf(text_buffer, 256,
231 rigid_bodies->bodies[id].x, rigid_bodies->bodies[id].y,
232 rigid_bodies->velocities[id].x, rigid_bodies->velocities[id].y,
233 rigid_bodies->movements[id].x, rigid_bodies->movements[id].y);
235 if (camera_render_debug_text(
238 vec(rigid_bodies->bodies[id].x,
239 rigid_bodies->bodies[id].y)) < 0) {
245 RigidBodyId rigid_bodies_add(RigidBodies *rigid_bodies,
248 trace_assert(rigid_bodies);
249 trace_assert(rigid_bodies->count < rigid_bodies->capacity);
251 RigidBodyId id = rigid_bodies->count++;
252 rigid_bodies->bodies[id] = rect;
257 void rigid_bodies_remove(RigidBodies *rigid_bodies,
260 trace_assert(rigid_bodies);
261 trace_assert(id < rigid_bodies->capacity);
263 rigid_bodies->deleted[id] = true;
266 Rect rigid_bodies_hitbox(const RigidBodies *rigid_bodies,
269 trace_assert(rigid_bodies);
270 trace_assert(id < rigid_bodies->count);
272 return rigid_bodies->bodies[id];
275 void rigid_bodies_move(RigidBodies *rigid_bodies,
279 trace_assert(rigid_bodies);
280 trace_assert(id < rigid_bodies->count);
282 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
286 rigid_bodies->movements[id] = movement;
289 int rigid_bodies_touches_ground(const RigidBodies *rigid_bodies,
292 trace_assert(rigid_bodies);
293 trace_assert(id < rigid_bodies->count);
295 return rigid_bodies->grounded[id];
298 void rigid_bodies_apply_omniforce(RigidBodies *rigid_bodies,
301 for (size_t i = 0; i < rigid_bodies->count; ++i) {
302 rigid_bodies_apply_force(rigid_bodies, i, force);
306 void rigid_bodies_apply_force(RigidBodies * rigid_bodies,
310 trace_assert(rigid_bodies);
311 trace_assert(id < rigid_bodies->count);
313 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
317 rigid_bodies->forces[id] = vec_sum(rigid_bodies->forces[id], force);
320 void rigid_bodies_transform_velocity(RigidBodies *rigid_bodies,
324 trace_assert(rigid_bodies);
325 trace_assert(id < rigid_bodies->count);
327 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
331 rigid_bodies->velocities[id] = point_mat3x3_product(
332 rigid_bodies->velocities[id],
336 void rigid_bodies_teleport_to(RigidBodies *rigid_bodies,
340 trace_assert(rigid_bodies);
341 trace_assert(id < rigid_bodies->count);
343 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
347 rigid_bodies->bodies[id].x = position.x;
348 rigid_bodies->bodies[id].y = position.y;
351 void rigid_bodies_damper(RigidBodies *rigid_bodies,
355 trace_assert(rigid_bodies);
356 trace_assert(id < rigid_bodies->count);
358 if (rigid_bodies->deleted[id] || rigid_bodies->disabled[id]) {
362 rigid_bodies_apply_force(
365 rigid_bodies->velocities[id].x * v.x,
366 rigid_bodies->velocities[id].y * v.y));
369 void rigid_bodies_disable(RigidBodies *rigid_bodies,
373 trace_assert(rigid_bodies);
374 trace_assert(id < rigid_bodies->count);
376 rigid_bodies->disabled[id] = disabled;