6 #include "game/level/boxes.h"
7 #include "game/level/solid.h"
8 #include "rigid_rect.h"
9 #include "system/error.h"
10 #include "system/lt.h"
12 #define RIGID_RECT_GRAVITY 1500.0f
24 static const vec_t opposing_rect_side_forces[RECT_SIDE_N] = {
25 { .x = 1.0f, .y = 0.0f }, /* RECT_SIDE_LEFT = 0, */
26 { .x = -1.0f, .y = 0.0f }, /* RECT_SIDE_RIGHT, */
27 { .x = 0.0f, .y = 1.0f, }, /* RECT_SIDE_TOP, */
28 { .x = 0.0f, .y = -1.0f, } /* RECT_SIDE_BOTTOM, */
31 static vec_t opposing_force_by_sides(int sides[RECT_SIDE_N])
33 vec_t opposing_force = {
38 for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) {
42 opposing_rect_side_forces[side]);
46 return opposing_force;
49 rigid_rect_t *create_rigid_rect(rect_t rect, color_t color)
51 lt_t *lt = create_lt();
57 rigid_rect_t *rigid_rect = PUSH_LT(lt, malloc(sizeof(rigid_rect_t)), free);
58 if (rigid_rect == NULL) {
59 throw_error(ERROR_TYPE_LIBC);
64 rigid_rect->position = vec(rect.x, rect.y);
65 rigid_rect->velocity = vec(0.0f, 0.0f);
66 rigid_rect->movement = vec(0.0f, 0.0f);
67 rigid_rect->size = vec(rect.w, rect.h);
68 rigid_rect->color = color;
69 rigid_rect->touches_ground = 0;
74 rigid_rect_t *create_rigid_rect_from_stream(FILE *stream)
81 if (fscanf(stream, "%f%f%f%f%6s\n",
85 throw_error(ERROR_TYPE_LIBC);
89 return create_rigid_rect(rect, color_from_hexstr(color));
92 void destroy_rigid_rect(rigid_rect_t *rigid_rect)
94 RETURN_LT0(rigid_rect->lt);
97 solid_ref_t rigid_rect_as_solid(rigid_rect_t *rigid_rect)
99 const solid_ref_t ref = {
100 .tag = SOLID_RIGID_RECT,
107 void rigid_rect_touches_rect_sides(rigid_rect_t *rigid_rect,
109 int sides[RECT_SIDE_N])
111 rect_object_impact(object, rigid_rect_hitbox(rigid_rect), sides);
114 int rigid_rect_render(const rigid_rect_t *rigid_rect,
115 const camera_t *camera)
117 return camera_fill_rect(
119 rigid_rect_hitbox(rigid_rect),
124 int rigid_rect_update(rigid_rect_t * rigid_rect,
129 rigid_rect->touches_ground = 0;
131 rigid_rect->velocity.y += RIGID_RECT_GRAVITY * delta_time;
132 rigid_rect->position = vec_sum(
133 rigid_rect->position,
136 rigid_rect->velocity,
137 rigid_rect->movement),
143 void rigid_rect_collide_with_solid(rigid_rect_t * rigid_rect,
147 assert(rigid_rect != solid.ptr);
149 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
151 solid_touches_rect_sides(solid, rigid_rect_hitbox(rigid_rect), sides);
153 if (sides[RECT_SIDE_BOTTOM]) {
154 rigid_rect->touches_ground = 1;
157 vec_t opposing_force = opposing_force_by_sides(sides);
159 for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) {
160 rigid_rect->position = vec_sum(
161 rigid_rect->position,
166 if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
167 rigid_rect->velocity.x = 0.0f;
168 rigid_rect->movement.x = 0.0f;
171 if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
172 rigid_rect->velocity.y = 0.0f;
173 rigid_rect->movement.y = 0.0f;
176 memset(sides, 0, sizeof(int) * RECT_SIDE_N);
177 solid_touches_rect_sides(
179 rigid_rect_hitbox(rigid_rect),
181 opposing_force = opposing_force_by_sides(sides);
185 void rigid_rect_impact_rigid_rect(rigid_rect_t * rigid_rect,
186 rigid_rect_t *another_rect)
188 if (rects_overlap(rigid_rect_hitbox(rigid_rect), rigid_rect_hitbox(another_rect))) {
189 rigid_rect_move(another_rect,
191 rigid_rect->velocity,
192 rigid_rect->movement));
196 rect_t rigid_rect_hitbox(const rigid_rect_t *rigid_rect)
198 return rect_from_vecs(
199 rigid_rect->position,
203 void rigid_rect_move(rigid_rect_t *rigid_rect,
206 rigid_rect->movement = movement;
209 void rigid_rect_jump(rigid_rect_t *rigid_rect,
212 rigid_rect->velocity.y = -force;
215 int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect)
217 return rigid_rect->touches_ground;