#include <SDL2/SDL.h>
-#include <assert.h>
+#include "system/stacktrace.h"
#include <stdio.h>
#include "color.h"
#include "game/level/lava/wavy_rect.h"
#include "lava.h"
#include "math/rect.h"
-#include "system/error.h"
#include "system/lt.h"
+#include "system/line_stream.h"
+#include "system/nth_alloc.h"
+#include "system/log.h"
-struct lava_t {
- lt_t *lt;
+#define LAVA_BOINGNESS 2500.0f
+
+struct Lava {
+ Lt *lt;
size_t rects_count;
- wavy_rect_t **rects;
+ Wavy_rect **rects;
};
-lava_t *create_lava_from_stream(FILE *stream)
+Lava *create_lava_from_line_stream(LineStream *line_stream)
{
- assert(stream);
+ trace_assert(line_stream);
- lt_t *lt = create_lt();
- if (lt == NULL) {
- return NULL;
- }
+ Lt *lt = create_lt();
- lava_t *lava = PUSH_LT(lt, malloc(sizeof(lava_t)), free);
+ Lava *lava = PUSH_LT(lt, nth_calloc(1, sizeof(Lava)), free);
if (lava == NULL) {
- throw_error(ERROR_TYPE_LIBC);
RETURN_LT(lt, NULL);
}
- if (fscanf(stream, "%lu", &lava->rects_count) < 0) {
- throw_error(ERROR_TYPE_LIBC);
+ if (sscanf(
+ line_stream_next(line_stream),
+ "%lu",
+ &lava->rects_count) < 0) {
+ log_fail("Could not read amount of lavas\n");
RETURN_LT(lt, NULL);
}
- lava->rects = PUSH_LT(lt, malloc(sizeof(wavy_rect_t*) * lava->rects_count), free);
+ lava->rects = PUSH_LT(lt, nth_calloc(1, sizeof(Wavy_rect*) * lava->rects_count), free);
if (lava->rects == NULL) {
- throw_error(ERROR_TYPE_LIBC);
RETURN_LT(lt, NULL);
}
for (size_t i = 0; i < lava->rects_count; ++i) {
- lava->rects[i] = PUSH_LT(lt, create_wavy_rect_from_stream(stream), destroy_wavy_rect);
+ lava->rects[i] = PUSH_LT(lt, create_wavy_rect_from_line_stream(line_stream), destroy_wavy_rect);
if (lava->rects[i] == NULL) {
RETURN_LT(lt, NULL);
}
return lava;
}
-void destroy_lava(lava_t *lava)
+void destroy_lava(Lava *lava)
{
- assert(lava);
+ trace_assert(lava);
RETURN_LT0(lava->lt);
}
-int lava_render(const lava_t *lava,
- const camera_t *camera)
+/* TODO(#449): lava does not render its id in debug mode */
+int lava_render(const Lava *lava,
+ Camera *camera)
{
- assert(lava);
- assert(camera);
+ trace_assert(lava);
+ trace_assert(camera);
for (size_t i = 0; i < lava->rects_count; ++i) {
if (wavy_rect_render(lava->rects[i], camera) < 0) {
return 0;
}
-int lava_update(lava_t *lava, float delta_time)
+int lava_update(Lava *lava, float delta_time)
{
- assert(lava);
+ trace_assert(lava);
for (size_t i = 0; i < lava->rects_count; ++i) {
if (wavy_rect_update(lava->rects[i], delta_time) < 0) {
return 0;
}
-int lava_overlaps_rect(const lava_t *lava,
- rect_t rect)
+bool lava_overlaps_rect(const Lava *lava,
+ Rect rect)
{
- assert(lava);
+ trace_assert(lava);
for (size_t i = 0; i < lava->rects_count; ++i) {
- if (wavy_rect_overlaps(lava->rects[i], rect)) {
- return 1;
+ if (rects_overlap(wavy_rect_hitbox(lava->rects[i]), rect)) {
+ return true;
}
}
return 0;
}
-rect_t lava_overlap_area(const lava_t *lava,
- rect_t object)
+void lava_float_rigid_body(Lava *lava, RigidBodies *rigid_bodies, RigidBodyId id)
{
+ trace_assert(lava);
+
+ const Rect object_hitbox = rigid_bodies_hitbox(rigid_bodies, id);
for (size_t i = 0; i < lava->rects_count; ++i) {
- if (wavy_rect_overlaps(lava->rects[i], object)) {
- return wavy_rect_overlap_area(lava->rects[i], object);
+ const Rect lava_hitbox = wavy_rect_hitbox(lava->rects[i]);
+ if (rects_overlap(object_hitbox, lava_hitbox)) {
+ const Rect overlap_area = rects_overlap_area(object_hitbox, lava_hitbox);
+ const float k = overlap_area.w * overlap_area.h / (object_hitbox.w * object_hitbox.h);
+ rigid_bodies_apply_force(
+ rigid_bodies,
+ id,
+ vec(0.0f, -k * LAVA_BOINGNESS));
+ rigid_bodies_damper(rigid_bodies, id, vec(0.0f, -0.9f));
}
}
-
- return rect(0.0f, 0.0f, 0.0f, 0.0f);
}