]> git.lizzy.rs Git - nothing.git/blob - src/game/level/lava.c
create_lt() -> {0}
[nothing.git] / src / game / level / lava.c
1 #include <SDL2/SDL.h>
2 #include "system/stacktrace.h"
3 #include <stdio.h>
4
5 #include "color.h"
6 #include "game/level/lava/wavy_rect.h"
7 #include "lava.h"
8 #include "math/rect.h"
9 #include "system/lt.h"
10 #include "system/line_stream.h"
11 #include "system/nth_alloc.h"
12 #include "system/log.h"
13
14 #define LAVA_BOINGNESS 2500.0f
15
16 struct Lava {
17     Lt lt;
18     size_t rects_count;
19     Wavy_rect **rects;
20 };
21
22 Lava *create_lava_from_line_stream(LineStream *line_stream)
23 {
24     trace_assert(line_stream);
25
26     Lt lt = {0};
27     if (lt == NULL) {
28         return NULL;
29     }
30
31     Lava *lava = PUSH_LT(lt, nth_calloc(1, sizeof(Lava)), free);
32     if (lava == NULL) {
33         RETURN_LT(lt, NULL);
34     }
35
36     if (sscanf(
37             line_stream_next(line_stream),
38             "%lu",
39             &lava->rects_count) < 0) {
40         log_fail("Could not read amount of lavas\n");
41         RETURN_LT(lt, NULL);
42     }
43
44     lava->rects = PUSH_LT(lt, nth_calloc(1, sizeof(Wavy_rect*) * lava->rects_count), free);
45     if (lava->rects == NULL) {
46         RETURN_LT(lt, NULL);
47     }
48
49     for (size_t i = 0; i < lava->rects_count; ++i) {
50         lava->rects[i] = PUSH_LT(lt, create_wavy_rect_from_line_stream(line_stream), destroy_wavy_rect);
51         if (lava->rects[i] == NULL) {
52             RETURN_LT(lt, NULL);
53         }
54     }
55
56     lava->lt = lt;
57
58     return lava;
59 }
60
61 void destroy_lava(Lava *lava)
62 {
63     trace_assert(lava);
64     RETURN_LT0(lava->lt);
65 }
66
67 /* TODO(#449): lava does not render its id in debug mode */
68 int lava_render(const Lava *lava,
69                 Camera *camera)
70 {
71     trace_assert(lava);
72     trace_assert(camera);
73
74     for (size_t i = 0; i < lava->rects_count; ++i) {
75         if (wavy_rect_render(lava->rects[i], camera) < 0) {
76             return -1;
77         }
78     }
79
80     return 0;
81 }
82
83 int lava_update(Lava *lava, float delta_time)
84 {
85     trace_assert(lava);
86
87     for (size_t i = 0; i < lava->rects_count; ++i) {
88         if (wavy_rect_update(lava->rects[i], delta_time) < 0) {
89             return -1;
90         }
91     }
92
93     return 0;
94 }
95
96 bool lava_overlaps_rect(const Lava *lava,
97                         Rect rect)
98 {
99     trace_assert(lava);
100
101     for (size_t i = 0; i < lava->rects_count; ++i) {
102         if (rects_overlap(wavy_rect_hitbox(lava->rects[i]), rect)) {
103             return true;
104         }
105     }
106
107     return 0;
108 }
109
110 void lava_float_rigid_body(Lava *lava, RigidBodies *rigid_bodies, RigidBodyId id)
111 {
112     trace_assert(lava);
113
114     const Rect object_hitbox = rigid_bodies_hitbox(rigid_bodies, id);
115     for (size_t i = 0; i < lava->rects_count; ++i) {
116         const Rect lava_hitbox = wavy_rect_hitbox(lava->rects[i]);
117         if (rects_overlap(object_hitbox, lava_hitbox)) {
118             const Rect overlap_area = rects_overlap_area(object_hitbox, lava_hitbox);
119             const float k = overlap_area.w * overlap_area.h / (object_hitbox.w * object_hitbox.h);
120             rigid_bodies_apply_force(
121                 rigid_bodies,
122                 id,
123                 vec(0.0f, -k * LAVA_BOINGNESS));
124             rigid_bodies_damper(rigid_bodies, id, vec(0.0f, -0.9f));
125         }
126     }
127 }