]> git.lizzy.rs Git - nothing.git/blob - src/game/level/boxes.c
(#802) TODO
[nothing.git] / src / game / level / boxes.c
1 #include "system/stacktrace.h"
2
3 #include "broadcast.h"
4 #include "ebisp/builtins.h"
5 #include "ebisp/interpreter.h"
6 #include "game/level/boxes.h"
7 #include "game/level/player.h"
8 #include "game/level/rigid_bodies.h"
9 #include "math/rand.h"
10 #include "system/line_stream.h"
11 #include "system/log.h"
12 #include "system/lt.h"
13 #include "system/nth_alloc.h"
14
15 #define BOXES_CAPACITY 1000
16
17 struct Boxes
18 {
19     Lt *lt;
20     RigidBodies *rigid_bodies;
21     RigidBodyId *body_ids;
22     size_t count;
23 };
24
25 Boxes *create_boxes_from_line_stream(LineStream *line_stream, RigidBodies *rigid_bodies)
26 {
27     trace_assert(line_stream);
28
29     Lt *lt = create_lt();
30
31     if (lt == NULL) {
32         return NULL;
33     }
34
35     Boxes *boxes = PUSH_LT(lt, nth_alloc(sizeof(Boxes)), free);
36     if (boxes == NULL) {
37         RETURN_LT(lt, NULL);
38     }
39     boxes->lt = lt;
40
41     boxes->rigid_bodies = rigid_bodies;
42
43     if (sscanf(
44             line_stream_next(line_stream),
45             "%lu",
46             &boxes->count) == EOF) {
47         log_fail("Could not read amount of boxes\n");
48         RETURN_LT(lt, NULL);
49     }
50     log_info("Boxes count: %d\n", boxes->count);
51
52     trace_assert(boxes->count < BOXES_CAPACITY);
53
54     boxes->body_ids = PUSH_LT(lt, nth_alloc(sizeof(RigidBodyId) * BOXES_CAPACITY), free);
55     if (boxes->body_ids == NULL) {
56         RETURN_LT(lt, NULL);
57     }
58
59     for (size_t i = 0; i < boxes->count; ++i) {
60         boxes->body_ids[i] = rigid_bodies_add_from_line_stream(boxes->rigid_bodies, line_stream);
61     }
62
63     return boxes;
64 }
65
66 void destroy_boxes(Boxes *boxes)
67 {
68     trace_assert(boxes);
69
70     for (size_t i = 0; i < boxes->count; ++i) {
71         rigid_bodies_remove(boxes->rigid_bodies, boxes->body_ids[i]);
72     }
73
74     RETURN_LT0(boxes->lt);
75 }
76
77 int boxes_render(Boxes *boxes, Camera *camera)
78 {
79     trace_assert(boxes);
80     trace_assert(camera);
81
82     for (size_t i = 0; i < boxes->count; ++i) {
83         if (rigid_bodies_render(boxes->rigid_bodies, boxes->body_ids[i], camera) < 0) {
84             return -1;
85         }
86     }
87
88     return 0;
89 }
90
91 int boxes_update(Boxes *boxes,
92                  float delta_time)
93 {
94     trace_assert(boxes);
95     trace_assert(delta_time);
96
97     for (size_t i = 0; i < boxes->count; ++i) {
98         if (rigid_bodies_update(boxes->rigid_bodies, boxes->body_ids[i], delta_time) < 0) {
99             return -1;
100         }
101     }
102
103     return 0;
104 }
105
106 void boxes_float_in_lava(Boxes *boxes, Lava *lava)
107 {
108     trace_assert(boxes);
109     trace_assert(lava);
110
111     for (size_t i = 0; i < boxes->count; ++i) {
112         lava_float_rigid_body(lava, boxes->rigid_bodies, boxes->body_ids[i]);
113     }
114 }
115
116 int boxes_add_box(Boxes *boxes, Rect rect, Color color)
117 {
118     trace_assert(boxes);
119     trace_assert(boxes->count < BOXES_CAPACITY);
120
121     boxes->body_ids[boxes->count++] = rigid_bodies_add(boxes->rigid_bodies, rect, color);
122
123     return 0;
124 }
125
126 struct EvalResult
127 boxes_send(Boxes *boxes, Gc *gc, struct Scope *scope, struct Expr path)
128 {
129     trace_assert(boxes);
130     trace_assert(gc);
131     trace_assert(scope);
132
133     struct Expr target = void_expr();
134     struct Expr rest = void_expr();
135     struct EvalResult res = match_list(gc, "e*", path, &target, &rest);
136     if (res.is_error) {
137         return res;
138     }
139
140     if (symbol_p(target)) {
141         const char *action = target.atom->str;
142
143         if (strcmp(action, "new") == 0) {
144             struct Expr optional_args = void_expr();
145             long int x, y, w, h;
146             res = match_list(gc, "dddd*", rest, &x, &y, &w, &h, &optional_args);
147             if (res.is_error) {
148                 return res;
149             }
150
151             Color color = rgba(rand_float(1.0f), rand_float(1.0f), rand_float(1.0f), 1.0f);
152             if (!nil_p(optional_args)) {
153                 const char *color_hex = NULL;
154                 res = match_list(gc, "s*", optional_args, &color_hex, NULL);
155                 color = hexstr(color_hex);
156             }
157
158             boxes_add_box(boxes, rect((float) x, (float) y, (float) w, (float) h), color);
159
160             return eval_success(NIL(gc));
161         }
162
163         return unknown_target(gc, "box", action);
164     }
165
166     return wrong_argument_type(gc, "string-or-symbol-p", target);
167 }
168
169
170 int boxes_delete_at(Boxes *boxes, Vec position)
171 {
172     trace_assert(boxes);
173
174     for (size_t i = 0; i < boxes->count; ++i) {
175         const Rect hitbox = rigid_bodies_hitbox(
176             boxes->rigid_bodies,
177             boxes->body_ids[i]);
178         if (rect_contains_point(hitbox, position)) {
179             rigid_bodies_remove(boxes->rigid_bodies, boxes->body_ids[i]);
180             for (size_t j = i; j < boxes->count - 1; ++j) {
181                 boxes->body_ids[j] = boxes->body_ids[j + 1];
182             }
183             boxes->count--;
184             return 0;
185         }
186     }
187
188     return 0;
189 }