-#include <assert.h>
+#include "system/stacktrace.h"
+#include "broadcast.h"
+#include "ebisp/builtins.h"
+#include "ebisp/interpreter.h"
#include "game/level/boxes.h"
-#include "game/level/physical_world.h"
#include "game/level/player.h"
-#include "game/level/player/rigid_rect.h"
-#include "system/error.h"
+#include "game/level/rigid_bodies.h"
+#include "math/rand.h"
+#include "system/line_stream.h"
+#include "system/log.h"
#include "system/lt.h"
+#include "system/nth_alloc.h"
-struct boxes_t
+#define BOXES_CAPACITY 1000
+
+struct Boxes
{
- lt_t *lt;
+ Lt *lt;
+ RigidBodies *rigid_bodies;
+ RigidBodyId *body_ids;
size_t count;
- rigid_rect_t **bodies;
};
-boxes_t *create_boxes_from_stream(FILE *stream)
+Boxes *create_boxes_from_line_stream(LineStream *line_stream, RigidBodies *rigid_bodies)
{
- assert(stream);
+ trace_assert(line_stream);
- lt_t *lt = create_lt();
+ Lt *lt = create_lt();
if (lt == NULL) {
return NULL;
}
- boxes_t *boxes = PUSH_LT(lt, malloc(sizeof(boxes_t)), free);
+ Boxes *boxes = PUSH_LT(lt, nth_alloc(sizeof(Boxes)), free);
if (boxes == NULL) {
- throw_error(ERROR_TYPE_LIBC);
RETURN_LT(lt, NULL);
}
+ boxes->lt = lt;
+
+ boxes->rigid_bodies = rigid_bodies;
- if (fscanf(stream, "%lu", &boxes->count) == EOF) {
- throw_error(ERROR_TYPE_LIBC);
+ if (sscanf(
+ line_stream_next(line_stream),
+ "%lu",
+ &boxes->count) == EOF) {
+ log_fail("Could not read amount of boxes\n");
RETURN_LT(lt, NULL);
}
+ log_info("Boxes count: %d\n", boxes->count);
- boxes->bodies = PUSH_LT(lt, malloc(sizeof(rigid_rect_t*) * boxes->count), free);
- if (boxes->bodies == NULL) {
- throw_error(ERROR_TYPE_LIBC);
+ trace_assert(boxes->count < BOXES_CAPACITY);
+
+ boxes->body_ids = PUSH_LT(lt, nth_alloc(sizeof(RigidBodyId) * BOXES_CAPACITY), free);
+ if (boxes->body_ids == NULL) {
RETURN_LT(lt, NULL);
}
for (size_t i = 0; i < boxes->count; ++i) {
- boxes->bodies[i] = PUSH_LT(
- lt,
- create_rigid_rect_from_stream(stream),
- destroy_rigid_rect);
- if (boxes->bodies[i] == NULL) {
- RETURN_LT(lt, NULL);
- }
+ boxes->body_ids[i] = rigid_bodies_add_from_line_stream(boxes->rigid_bodies, line_stream);
}
- boxes->lt = lt;
-
return boxes;
}
-void destroy_boxes(boxes_t *boxes)
+void destroy_boxes(Boxes *boxes)
{
- assert(boxes);
+ trace_assert(boxes);
+
+ for (size_t i = 0; i < boxes->count; ++i) {
+ rigid_bodies_remove(boxes->rigid_bodies, boxes->body_ids[i]);
+ }
+
RETURN_LT0(boxes->lt);
}
-int boxes_render(boxes_t *boxes, camera_t *camera)
+int boxes_render(Boxes *boxes, Camera *camera)
{
- assert(boxes);
- assert(camera);
+ trace_assert(boxes);
+ trace_assert(camera);
for (size_t i = 0; i < boxes->count; ++i) {
- if (rigid_rect_render(boxes->bodies[i], camera) < 0) {
+ if (rigid_bodies_render(boxes->rigid_bodies, boxes->body_ids[i], camera) < 0) {
return -1;
}
}
return 0;
}
-int boxes_update(boxes_t *boxes,
+int boxes_update(Boxes *boxes,
float delta_time)
{
- assert(boxes);
- assert(delta_time);
+ trace_assert(boxes);
+ trace_assert(delta_time);
for (size_t i = 0; i < boxes->count; ++i) {
- if (rigid_rect_update(boxes->bodies[i], delta_time) < 0) {
+ if (rigid_bodies_update(boxes->rigid_bodies, boxes->body_ids[i], delta_time) < 0) {
return -1;
}
}
return 0;
}
-int boxes_add_to_physical_world(const boxes_t *boxes,
- physical_world_t *physical_world)
+void boxes_float_in_lava(Boxes *boxes, Lava *lava)
{
- assert(boxes);
- assert(physical_world);
+ trace_assert(boxes);
+ trace_assert(lava);
for (size_t i = 0; i < boxes->count; ++i) {
- if (physical_world_add_solid(
- physical_world,
- rigid_rect_as_solid(boxes->bodies[i])) < 0) {
- return -1;
+ lava_float_rigid_body(lava, boxes->rigid_bodies, boxes->body_ids[i]);
+ }
+}
+
+int boxes_add_box(Boxes *boxes, Rect rect, Color color)
+{
+ trace_assert(boxes);
+ trace_assert(boxes->count < BOXES_CAPACITY);
+
+ boxes->body_ids[boxes->count++] = rigid_bodies_add(boxes->rigid_bodies, rect, color);
+
+ return 0;
+}
+
+struct EvalResult
+boxes_send(Boxes *boxes, Gc *gc, struct Scope *scope, struct Expr path)
+{
+ trace_assert(boxes);
+ trace_assert(gc);
+ trace_assert(scope);
+
+ struct Expr target = void_expr();
+ struct Expr rest = void_expr();
+ struct EvalResult res = match_list(gc, "e*", path, &target, &rest);
+ if (res.is_error) {
+ return res;
+ }
+
+ if (symbol_p(target)) {
+ const char *action = target.atom->str;
+
+ if (strcmp(action, "new") == 0) {
+ struct Expr optional_args = void_expr();
+ long int x, y, w, h;
+ res = match_list(gc, "dddd*", rest, &x, &y, &w, &h, &optional_args);
+ if (res.is_error) {
+ return res;
+ }
+
+ Color color = rgba(rand_float(1.0f), rand_float(1.0f), rand_float(1.0f), 1.0f);
+ if (!nil_p(optional_args)) {
+ const char *color_hex = NULL;
+ res = match_list(gc, "s*", optional_args, &color_hex, NULL);
+ color = hexstr(color_hex);
+ }
+
+ boxes_add_box(boxes, rect((float) x, (float) y, (float) w, (float) h), color);
+
+ return eval_success(NIL(gc));
+ }
+
+ return unknown_target(gc, "box", action);
+ }
+
+ return wrong_argument_type(gc, "string-or-symbol-p", target);
+}
+
+
+int boxes_delete_at(Boxes *boxes, Vec position)
+{
+ trace_assert(boxes);
+
+ for (size_t i = 0; i < boxes->count; ++i) {
+ const Rect hitbox = rigid_bodies_hitbox(
+ boxes->rigid_bodies,
+ boxes->body_ids[i]);
+ if (rect_contains_point(hitbox, position)) {
+ rigid_bodies_remove(boxes->rigid_bodies, boxes->body_ids[i]);
+ for (size_t j = i; j < boxes->count - 1; ++j) {
+ boxes->body_ids[j] = boxes->body_ids[j + 1];
+ }
+ boxes->count--;
+ return 0;
}
}