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"
26 static const vec_t opposing_rect_side_forces[RECT_SIDE_N] = {
27 { .x = 1.0f, .y = 0.0f }, /* RECT_SIDE_LEFT = 0, */
28 { .x = -1.0f, .y = 0.0f }, /* RECT_SIDE_RIGHT, */
29 { .x = 0.0f, .y = 1.0f, }, /* RECT_SIDE_TOP, */
30 { .x = 0.0f, .y = -1.0f, } /* RECT_SIDE_BOTTOM, */
33 static vec_t opposing_force_by_sides(int sides[RECT_SIDE_N])
35 vec_t opposing_force = {
40 for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) {
44 opposing_rect_side_forces[side]);
48 return opposing_force;
51 rigid_rect_t *create_rigid_rect(rect_t rect, color_t color)
53 lt_t *lt = create_lt();
59 rigid_rect_t *rigid_rect = PUSH_LT(lt, malloc(sizeof(rigid_rect_t)), free);
60 if (rigid_rect == NULL) {
61 throw_error(ERROR_TYPE_LIBC);
66 rigid_rect->position = vec(rect.x, rect.y);
67 rigid_rect->velocity = vec(0.0f, 0.0f);
68 rigid_rect->movement = vec(0.0f, 0.0f);
69 rigid_rect->size = vec(rect.w, rect.h);
70 rigid_rect->color = color;
71 rigid_rect->touches_ground = 0;
72 rigid_rect->floating = 0.0f;
73 rigid_rect->forces = vec(0.0f, 0.0f);
78 rigid_rect_t *create_rigid_rect_from_stream(FILE *stream)
85 if (fscanf(stream, "%f%f%f%f%6s\n",
89 throw_error(ERROR_TYPE_LIBC);
93 return create_rigid_rect(rect, color_from_hexstr(color));
96 void destroy_rigid_rect(rigid_rect_t *rigid_rect)
98 RETURN_LT0(rigid_rect->lt);
101 solid_ref_t rigid_rect_as_solid(rigid_rect_t *rigid_rect)
103 const solid_ref_t ref = {
104 .tag = SOLID_RIGID_RECT,
111 void rigid_rect_touches_rect_sides(rigid_rect_t *rigid_rect,
113 int sides[RECT_SIDE_N])
115 rect_object_impact(object, rigid_rect_hitbox(rigid_rect), sides);
118 int rigid_rect_render(const rigid_rect_t *rigid_rect,
119 const camera_t *camera)
121 return camera_fill_rect(
123 rigid_rect_hitbox(rigid_rect),
128 int rigid_rect_update(rigid_rect_t * rigid_rect,
133 rigid_rect->touches_ground = 0;
135 /* TODO(#207): rigid_rect floating in lava is broken */
136 rigid_rect->velocity = vec_sum(
137 rigid_rect->velocity,
142 rigid_rect->position = vec_sum(
143 rigid_rect->position,
146 rigid_rect->velocity,
147 rigid_rect->movement),
150 rigid_rect->forces = vec(0.0f, 0.0f);
155 void rigid_rect_collide_with_solid(rigid_rect_t * rigid_rect,
159 assert(rigid_rect != solid.ptr);
161 int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
163 solid_touches_rect_sides(solid, rigid_rect_hitbox(rigid_rect), sides);
165 if (sides[RECT_SIDE_BOTTOM]) {
166 rigid_rect->touches_ground = 1;
169 vec_t opforce_direction = opposing_force_by_sides(sides);
174 vec_neg(vec_norm(opforce_direction)),
177 rigid_rect->velocity,
178 rigid_rect->movement)) * 8.0f));
180 if (fabs(opforce_direction.x) > 1e-6 && (opforce_direction.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
181 rigid_rect->velocity.x = 0.0f;
182 rigid_rect->movement.x = 0.0f;
185 if (fabs(opforce_direction.y) > 1e-6 && (opforce_direction.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
186 rigid_rect->velocity.y = 0.0f;
187 rigid_rect->movement.y = 0.0f;
189 if (vec_length(rigid_rect->velocity) > 1e-6) {
190 rigid_rect_apply_force(
193 vec_neg(rigid_rect->velocity),
199 for (int i = 0; i < 1000 && vec_length(opforce_direction) > 1e-6; ++i) {
200 rigid_rect->position = vec_sum(
201 rigid_rect->position,
206 memset(sides, 0, sizeof(int) * RECT_SIDE_N);
207 solid_touches_rect_sides(
209 rigid_rect_hitbox(rigid_rect),
211 opforce_direction = opposing_force_by_sides(sides);
215 rect_t rigid_rect_hitbox(const rigid_rect_t *rigid_rect)
217 return rect_from_vecs(
218 rigid_rect->position,
222 void rigid_rect_move(rigid_rect_t *rigid_rect,
225 rigid_rect->movement = movement;
228 int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect)
230 return rigid_rect->touches_ground;
233 void rigid_rect_collide_with_lava(rigid_rect_t *rigid_rect,
239 rect_t overlap_area = lava_overlap_area(lava, rigid_rect_hitbox(rigid_rect));
240 rigid_rect->floating = (overlap_area.w * overlap_area.h) / (rigid_rect->size.x * rigid_rect->size.y);
243 void rigid_rect_apply_force(rigid_rect_t * rigid_rect,
246 rigid_rect->forces = vec_sum(rigid_rect->forces, force);
249 void rigid_rect_transform_velocity(rigid_rect_t *rigid_rect,
252 rigid_rect->velocity = point_mat3x3_product(rigid_rect->velocity,