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