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"
16 #define RIGID_BODIES_MAX_ID_SIZE 36
21 // TODO(#685): capacity is not needed in RigidBodies
33 RigidBodies *create_rigid_bodies(size_t capacity)
40 RigidBodies *rigid_bodies = PUSH_LT(lt, nth_calloc(1, sizeof(RigidBodies)), free);
41 if (rigid_bodies == NULL) {
44 rigid_bodies->lt = lt;
46 rigid_bodies->capacity = capacity;
47 rigid_bodies->count = 0;
49 rigid_bodies->bodies = PUSH_LT(lt, nth_calloc(capacity, sizeof(Rect)), free);
50 if (rigid_bodies->bodies == NULL) {
54 rigid_bodies->velocities = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
55 if (rigid_bodies->velocities == NULL) {
59 rigid_bodies->movements = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
60 if (rigid_bodies->movements == NULL) {
64 rigid_bodies->colors = PUSH_LT(lt, nth_calloc(capacity, sizeof(Color)), free);
65 if (rigid_bodies->colors == NULL) {
69 rigid_bodies->grounded = PUSH_LT(lt, nth_calloc(capacity, sizeof(bool)), free);
70 if (rigid_bodies->grounded == NULL) {
74 rigid_bodies->forces = PUSH_LT(lt, nth_calloc(capacity, sizeof(Vec)), free);
75 if (rigid_bodies->forces == NULL) {
82 void destroy_rigid_bodies(RigidBodies *rigid_bodies)
84 trace_assert(rigid_bodies);
85 RETURN_LT0(rigid_bodies->lt);
88 static int rigid_bodies_collide_with_itself(RigidBodies *rigid_bodies)
90 trace_assert(rigid_bodies);
92 if (rigid_bodies->count == 0) {
96 for (size_t i1 = 0; i1 < rigid_bodies->count - 1; ++i1) {
97 for (size_t i2 = i1 + 1; i2 < rigid_bodies->count; ++i2) {
98 if (!rects_overlap(rigid_bodies->bodies[i1], rigid_bodies->bodies[i2])) {
102 rect_impulse(&rigid_bodies->bodies[i1], &rigid_bodies->bodies[i2]);
104 const Vec v1 = rigid_bodies->velocities[i1];
105 const Vec v2 = rigid_bodies->velocities[i2];
106 rigid_bodies->velocities[i1] = v2;
107 rigid_bodies->velocities[i2] = v1;
114 static int rigid_bodies_collide_with_platforms(
115 RigidBodies *rigid_bodies,
116 const Platforms *platforms)
118 trace_assert(rigid_bodies);
119 trace_assert(platforms);
121 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
123 for (size_t i = 0; i < rigid_bodies->count; ++i) {
124 memset(sides, 0, sizeof(int) * RECT_SIDE_N);
126 platforms_touches_rect_sides(platforms, rigid_bodies->bodies[i], sides);
128 if (sides[RECT_SIDE_BOTTOM]) {
129 rigid_bodies->grounded[i] = true;
132 Vec v = platforms_snap_rect(platforms, &rigid_bodies->bodies[i]);
133 rigid_bodies->velocities[i] = vec_entry_mult(rigid_bodies->velocities[i], v);
134 rigid_bodies->movements[i] = vec_entry_mult(rigid_bodies->movements[i], v);
135 rigid_bodies_damper(rigid_bodies, i, vec_entry_mult(v, vec(-16.0f, 0.0f)));
141 int rigid_bodies_collide(RigidBodies *rigid_bodies,
142 const Platforms *platforms)
144 // TODO(#683): RigidBodies should collide only the bodies that were updated on after a previous collision
145 memset(rigid_bodies->grounded, 0, sizeof(bool) * rigid_bodies->count);
147 if (rigid_bodies_collide_with_itself(rigid_bodies) < 0) {
151 if (rigid_bodies_collide_with_platforms(rigid_bodies, platforms) < 0) {
158 int rigid_bodies_update(RigidBodies *rigid_bodies,
162 trace_assert(rigid_bodies);
164 rigid_bodies->velocities[id] = vec_sum(
165 rigid_bodies->velocities[id],
167 rigid_bodies->forces[id],
170 Vec position = vec(rigid_bodies->bodies[id].x,
171 rigid_bodies->bodies[id].y);
177 rigid_bodies->velocities[id],
178 rigid_bodies->movements[id]),
181 rigid_bodies->bodies[id].x = position.x;
182 rigid_bodies->bodies[id].y = position.y;
184 rigid_bodies->forces[id] = vec(0.0f, 0.0f);
189 int rigid_bodies_render(RigidBodies *rigid_bodies,
193 trace_assert(rigid_bodies);
194 trace_assert(camera);
196 char text_buffer[256];
198 if (camera_fill_rect(
200 rigid_bodies->bodies[id],
201 rigid_bodies->colors[id]) < 0) {
205 snprintf(text_buffer, ID_SIZE, "id: %ld", id);
207 if (camera_render_debug_text(
210 vec(rigid_bodies->bodies[id].x,
211 rigid_bodies->bodies[id].y)) < 0) {
215 snprintf(text_buffer, 256, "pos:(%f, %f)",
216 rigid_bodies->bodies[id].x,
217 rigid_bodies->bodies[id].y);
218 if (camera_render_debug_text(
221 vec(rigid_bodies->bodies[id].x,
222 rigid_bodies->bodies[id].y + FONT_CHAR_HEIGHT * 2.0f))) {
229 RigidBodyId rigid_bodies_add(RigidBodies *rigid_bodies,
233 trace_assert(rigid_bodies);
234 trace_assert(rigid_bodies->count < rigid_bodies->capacity);
236 RigidBodyId id = rigid_bodies->count++;
237 rigid_bodies->bodies[id] = rect;
238 rigid_bodies->colors[id] = color;
243 RigidBodyId rigid_bodies_add_from_line_stream(RigidBodies *rigid_bodies,
244 LineStream *line_stream)
246 trace_assert(rigid_bodies);
247 trace_assert(line_stream);
251 // TODO(#686): id should be part of boxes
252 char id[RIGID_BODIES_MAX_ID_SIZE];
254 if (sscanf(line_stream_next(line_stream),
255 "%" STRINGIFY(RIGID_BODIES_MAX_ID_SIZE) "s%f%f%f%f%6s\n",
260 log_fail("Could not read rigid rect\n");
261 // TODO(#687): rigid_bodies_add_from_line_stream cannot indicate an error properly
265 return rigid_bodies_add(rigid_bodies, rect, hexstr(color));
268 Rect rigid_bodies_hitbox(const RigidBodies *rigid_bodies,
271 trace_assert(rigid_bodies);
272 trace_assert(id < rigid_bodies->count);
274 return rigid_bodies->bodies[id];
277 void rigid_bodies_move(RigidBodies *rigid_bodies,
281 trace_assert(rigid_bodies);
282 trace_assert(id < rigid_bodies->count);
284 rigid_bodies->movements[id] = movement;
287 int rigid_bodies_touches_ground(const RigidBodies *rigid_bodies,
290 trace_assert(rigid_bodies);
291 trace_assert(id < rigid_bodies->count);
293 return rigid_bodies->grounded[id];
296 void rigid_bodies_apply_omniforce(RigidBodies *rigid_bodies,
299 for (size_t i = 0; i < rigid_bodies->count; ++i) {
300 rigid_bodies_apply_force(rigid_bodies, i, force);
304 void rigid_bodies_apply_force(RigidBodies * rigid_bodies,
308 trace_assert(rigid_bodies);
309 trace_assert(id < rigid_bodies->count);
311 rigid_bodies->forces[id] = vec_sum(rigid_bodies->forces[id], force);
314 void rigid_bodies_transform_velocity(RigidBodies *rigid_bodies,
318 trace_assert(rigid_bodies);
319 trace_assert(id < rigid_bodies->count);
321 rigid_bodies->velocities[id] = point_mat3x3_product(
322 rigid_bodies->velocities[id],
326 void rigid_bodies_teleport_to(RigidBodies *rigid_bodies,
330 trace_assert(rigid_bodies);
331 trace_assert(id < rigid_bodies->count);
333 rigid_bodies->bodies[id].x = position.x;
334 rigid_bodies->bodies[id].y = position.y;
337 void rigid_bodies_damper(RigidBodies *rigid_bodies,
341 trace_assert(rigid_bodies);
342 trace_assert(id < rigid_bodies->count);
344 rigid_bodies_apply_force(
347 rigid_bodies->velocities[id].x * v.x,
348 rigid_bodies->velocities[id].y * v.y));