6 #include "rigid_rect.h"
7 #include "system/error.h"
9 #include "game/level/boxes.h"
11 #define RIGID_RECT_GRAVITY 1500.0f
23 static const vec_t opposing_rect_side_forces[RECT_SIDE_N] = {
24 { .x = 1.0f, .y = 0.0f }, /* RECT_SIDE_LEFT = 0, */
25 { .x = -1.0f, .y = 0.0f }, /* RECT_SIDE_RIGHT, */
26 { .x = 0.0f, .y = 1.0f, }, /* RECT_SIDE_TOP, */
27 { .x = 0.0f, .y = -1.0f, } /* RECT_SIDE_BOTTOM, */
30 static vec_t opposing_force_by_sides(int sides[RECT_SIDE_N])
32 vec_t opposing_force = {
37 for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) {
41 opposing_rect_side_forces[side]);
45 return opposing_force;
48 rigid_rect_t *create_rigid_rect(rect_t rect, color_t color)
50 lt_t *lt = create_lt();
56 rigid_rect_t *rigid_rect = PUSH_LT(lt, malloc(sizeof(rigid_rect_t)), free);
57 if (rigid_rect == NULL) {
58 throw_error(ERROR_TYPE_LIBC);
63 rigid_rect->position = vec(rect.x, rect.y);
64 rigid_rect->velocity = vec(0.0f, 0.0f);
65 rigid_rect->movement = vec(0.0f, 0.0f);
66 rigid_rect->size = vec(rect.w, rect.h);
67 rigid_rect->color = color;
68 rigid_rect->touches_ground = 0;
73 rigid_rect_t *create_rigid_rect_from_stream(FILE *stream)
80 if (fscanf(stream, "%f%f%f%f%6s\n",
84 throw_error(ERROR_TYPE_LIBC);
88 return create_rigid_rect(rect, color_from_hexstr(color));
91 void destroy_rigid_rect(rigid_rect_t *rigid_rect)
93 RETURN_LT0(rigid_rect->lt);
96 int rigid_rect_render(const rigid_rect_t *rigid_rect,
97 const camera_t *camera)
99 return camera_fill_rect(
101 rigid_rect_hitbox(rigid_rect),
106 int rigid_rect_update(rigid_rect_t * rigid_rect,
111 rigid_rect->touches_ground = 0;
113 rigid_rect->velocity.y += RIGID_RECT_GRAVITY * delta_time;
114 rigid_rect->position = vec_sum(
115 rigid_rect->position,
118 rigid_rect->velocity,
119 rigid_rect->movement),
125 void rigid_rect_collide_with_platforms(rigid_rect_t * rigid_rect,
126 const platforms_t *platforms)
128 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
130 platforms_rect_object_collide(platforms, rigid_rect_hitbox(rigid_rect), sides);
132 if (sides[RECT_SIDE_BOTTOM]) {
133 rigid_rect->touches_ground = 1;
136 vec_t opposing_force = opposing_force_by_sides(sides);
138 for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) {
139 rigid_rect->position = vec_sum(
140 rigid_rect->position,
145 if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
146 rigid_rect->velocity.x = 0.0f;
147 rigid_rect->movement.x = 0.0f;
150 if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
151 rigid_rect->velocity.y = 0.0f;
152 rigid_rect->movement.y = 0.0f;
155 platforms_rect_object_collide(
157 rigid_rect_hitbox(rigid_rect),
159 opposing_force = opposing_force_by_sides(sides);
163 void rigid_rect_collide_with_rect(rigid_rect_t * rigid_rect,
166 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
168 const rect_t object = rect_from_vecs(rigid_rect->position, rigid_rect->size);
169 rect_object_impact(&object, &rect, sides);
171 if (sides[RECT_SIDE_BOTTOM]) {
172 rigid_rect->touches_ground = 1;
175 vec_t opposing_force = opposing_force_by_sides(sides);
177 for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) {
178 rigid_rect->position = vec_sum(
179 rigid_rect->position,
184 if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
185 rigid_rect->velocity.x = 0.0f;
186 rigid_rect->movement.x = 0.0f;
189 if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
190 rigid_rect->velocity.y = 0.0f;
191 rigid_rect->movement.y = 0.0f;
194 rect_object_impact(&object, &rect, sides);
195 opposing_force = opposing_force_by_sides(sides);
199 void rigid_rect_collide_with_boxes(rigid_rect_t * rigid_rect,
200 const boxes_t *boxes)
202 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
204 boxes_rect_object_collide(boxes, rigid_rect_hitbox(rigid_rect), sides);
206 if (sides[RECT_SIDE_BOTTOM]) {
207 rigid_rect->touches_ground = 1;
210 vec_t opposing_force = opposing_force_by_sides(sides);
212 for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) {
213 rigid_rect->position = vec_sum(
214 rigid_rect->position,
219 if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
220 rigid_rect->velocity.x = 0.0f;
221 rigid_rect->movement.x = 0.0f;
224 if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
225 rigid_rect->velocity.y = 0.0f;
226 rigid_rect->movement.y = 0.0f;
229 boxes_rect_object_collide(
231 rigid_rect_hitbox(rigid_rect),
233 opposing_force = opposing_force_by_sides(sides);
237 void rigid_rect_impact_rigid_rect(rigid_rect_t * rigid_rect,
238 rigid_rect_t *another_rect)
240 if (rects_overlap(rigid_rect_hitbox(rigid_rect), rigid_rect_hitbox(another_rect))) {
241 rigid_rect_move(another_rect,
243 rigid_rect->velocity,
244 rigid_rect->movement));
248 rect_t rigid_rect_hitbox(const rigid_rect_t *rigid_rect)
250 return rect_from_vecs(
251 rigid_rect->position,
255 void rigid_rect_move(rigid_rect_t *rigid_rect,
258 rigid_rect->movement = movement;
261 void rigid_rect_jump(rigid_rect_t *rigid_rect,
264 rigid_rect->velocity.y = -force;
267 int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect)
269 return rigid_rect->touches_ground;